Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Documented 4 functions across 1 file #147

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions apps/getting-started/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,17 @@
"main": "index.js",
"scripts": {
"develop": "flatfile develop index.ts",
"deploy": "flatfile deploy index.ts",
"paginate": "flatfile develop paginate-records.ts"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"@flatfile/api": "^1.8.5",
"@flatfile/cross-env-config": "*",
"@flatfile/hooks": "^1.3.0",
"@flatfile/api": "^1.8.5",
"@flatfile/listener": "^1.0.5",
"@flatfile/plugin-record-hook": "^1.5.2",
"actions": "^1.3.0",
"ansi-colors": "^4.1.3",
Expand All @@ -28,4 +30,4 @@
"devDependencies": {
"@types/node": "^18.16.0"
}
}
}
13 changes: 7 additions & 6 deletions package-lock.json

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

120 changes: 107 additions & 13 deletions packages/cli/src/x/actions/deploy.action.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,29 @@ const readPackageJson = util.promisify(require('read-package-json'))

type ListenerTopics = Flatfile.EventTopic | '**'

/**
* @description Handles selecting an agent from a list of agents based on user input.
* If multiple agents are provided, it prompts the user to select one. Otherwise, it
* returns the first or only agent depending on the input.
*
* @param {Flatfile.Agent[] | undefined} data - list of Flatfile.Agent objects that
* can be filtered or selected by the user based on their slugs or other properties.
*
* @param {string | undefined} slug - identifier assigned to each agent in the
* environment, which the function uses to find and return the selected agent.
*
* @param {ora.Ora} validatingSpinner - ora spinner used to display informative failure
* messages when multiple agents are found in the environment.
*
* @returns {Flatfile.Agent} a selected agent from a list of multiple agents, based
* on user input.
*
* * `data`: The found agent or `undefined` if there's no data.
* * `slug`: The selected slug or `<no-slug>` if no slug was provided.
* * `validatingSpinner`: The Ora spinner used for validating the selection process.
*
* The output is directly returned without any additional summaries or information.
*/
async function handleAgentSelection(
data: Flatfile.Agent[] | undefined,
slug: string | undefined,
Expand Down Expand Up @@ -73,38 +96,99 @@ async function handleAgentSelection(
}
}

function findActiveTopics(allTopics: ListenerTopics[], client: any, topicsWithListeners = new Set()) {
/**
* @description Processes a list of listener topics and sub-clients to filter and
* identify active topics based on inclusion patterns. It iterates over the listeners,
* nodes, and topics to find matching and non-matching patterns and add them to a Set
* data structure for further processing.
*
* @param {ListenerTopics[]} allTopics - list of all topics that the listener is
* interested in, which are filtered and added to a new Set data structure to form
* the active topics list returned by the function.
*
* @param {any} client - client to search for listeners in, and its `listeners`
* property is traversed to find active topics.
*
* @param {new_expression} topicsWithListeners - Set of all the active topics that
* have listeners attached to them after filtering out any cron events and iterating
* over nested clients.
*
* @returns {object} a set of top-level and nested topics with listeners.
*/
function findActiveTopics(
allTopics: ListenerTopics[],
client: any,
topicsWithListeners = new Set()
) {
client.listeners?.forEach((listener: ListenerTopics | ListenerTopics[]) => {
const listenerTopics = Array.isArray(listener[0]) ? listener[0] : [listener[0]]
listenerTopics.forEach(listenerTopic => {
const listenerTopics = Array.isArray(listener[0])
? listener[0]
: [listener[0]]
listenerTopics.forEach((listenerTopic) => {
if (listenerTopic === '**') {
// Filter cron events out of '**' list - they must be added explicitly
const filteredTopics = allTopics.filter(event => !event.startsWith('cron:'))
filteredTopics.forEach(topic => topicsWithListeners.add(topic))
const filteredTopics = allTopics.filter(
(event) => !event.startsWith('cron:')
)
filteredTopics.forEach((topic) => topicsWithListeners.add(topic))
} else if (listenerTopic.includes('**')) {
const [prefix] = listenerTopic.split(':')
allTopics.forEach(topic => { if (topic.split(':')[0] === prefix) topicsWithListeners.add(topic) })
allTopics.forEach((topic) => {
if (topic.split(':')[0] === prefix) topicsWithListeners.add(topic)
})
} else if (allTopics.includes(listenerTopic)) {
topicsWithListeners.add(listenerTopic)
}
})
})
client.nodes?.forEach((nestedClient: any) => findActiveTopics(allTopics, nestedClient, topicsWithListeners))
client.nodes?.forEach((nestedClient: any) =>
findActiveTopics(allTopics, nestedClient, topicsWithListeners)
)
return topicsWithListeners
}

async function getActiveTopics(file: string): Promise<Flatfile.EventTopic[]>{
/**
* @description Retrieves a list of active topics from a given file and returns them
* as an array of `Flatfile.EventTopic`.
*
* @param {string} file - Flatfile file to be analyzed for active topics, and the
* function retrieves and returns an array of event topics from that file.
*
* @returns {Promise<Flatfile.EventTopic[]>} an array of Flatfile event topics.
*/
async function getActiveTopics(file: string): Promise<Flatfile.EventTopic[]> {
const allTopics = Object.values(Flatfile.events.EventTopic)

let mount
try {
mount = await import(url.pathToFileURL(file).href)
} catch(e) {
} catch (e) {
return program.error(messages.error(e))
}
return Array.from(findActiveTopics(allTopics, mount.default)) as Flatfile.EventTopic[];
return Array.from(
findActiveTopics(allTopics, mount.default)
) as Flatfile.EventTopic[]
}

/**
* @description * Deploys an event listener to a Flatfile environment using an
* authenticated API client
* * Creates a build package from a source file, validates it, and deploys it to the
* environment.
*
* @param {string | null | undefined} file - entry file for Flatfile, which is used
* to compile and deploy an event listener code package.
*
* @param {Partial<{
* slug: string
* topics: string
* apiUrl: string
* token: string
* }>} options - 2-level nested object that allows passing various deployment
* configuration settings, including the `slug`, `topics`, `apiUrl`, and `token` properties.
*
* @returns {Promise<void>} a list of events generated by the deployed event listener.
*/
export async function deployAction(
file?: string | null | undefined,
options?: Partial<{
Expand Down Expand Up @@ -164,8 +248,10 @@ export async function deployAction(
path.basename(file!)
)
)

const fileContent = fs.readFileSync(file, 'utf8')
console.log({ file, fileContent })
const entry = result.split(path.sep).join(path.posix.sep)
// console.log({ entry })
fs.writeFileSync(path.join(outDir, '_entry.js'), entry, 'utf8')
const buildingSpinner = ora({
text: `Building deployable code package`,
Expand Down Expand Up @@ -204,9 +290,10 @@ export async function deployAction(
}).start()

try {
const { err, code } = await ncc(path.join(outDir, '_entry.js'), {
const { err, code, map } = await ncc(path.join(outDir, '_entry.js'), {
minify: liteMode,
target: 'es2020',
sourceMap: true,
cache: false,
// TODO: add debug flag to add this and other debug options
quiet: true,
Expand All @@ -215,7 +302,11 @@ export async function deployAction(

const deployFile = path.join(outDir, 'deploy.js')
fs.writeFileSync(deployFile, code, 'utf8')
const activeTopics: Flatfile.EventTopic[] = await getActiveTopics(deployFile)
const mapFile = path.join(outDir, 'deploy.js.map')
fs.writeFileSync(mapFile, map, 'utf8')
const activeTopics: Flatfile.EventTopic[] = await getActiveTopics(
deployFile
)

if (err) {
return program.error(messages.error(err))
Expand All @@ -227,6 +318,9 @@ export async function deployAction(
topics: activeTopics,
compiler: 'js',
source: code,
// TODO: Add this to the Agent Table
// @ts-ignore
map,
slug: slug ?? selectedAgent?.slug,
},
})
Expand Down