Skip to content
Merged
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
15 changes: 15 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# Salla App Functions — environment
#
# Copy this file to `.env` and fill in your own values:
#
# cp .env.example .env
#
# `.env` is gitignored. It configures the Salla CLI on your machine only — it is
# NOT shipped to the deployed function. Per-merchant secrets (API keys, URLs)
# belong in your app's settings form, which arrives as `context.settings`.

# The Partner app your functions deploy to.
# Find it in the Partner Portal (https://salla.partners/), or run `salla app list`.
# Without it you must pass the id on every command:
# salla app functions deploy <app_id>
SALLA_APP_ID=1234567890
2 changes: 1 addition & 1 deletion .github/CODEOWNERS
Original file line number Diff line number Diff line change
@@ -1 +1 @@
* @SallaApp/opensource
* @SallaApp/opensource @mzfrshk @muhammad-shaeel
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,8 @@ Thumbs.db
*~
*.bak
*.tmp

pnpm-lock.yaml
pnpm-workspace.yaml
package-lock.json
yarn.lock
454 changes: 390 additions & 64 deletions README.md

Large diffs are not rendered by default.

11 changes: 6 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
{
"name": "app-functions-cli-template",
"name": "app-functions-starter-kit",
"version": "1.0.0",
"private": true,
"type": "module",
"description": "Template to create App Functions with Salla CLI.",
"description": "Starter kit to create App Functions with Salla CLI.",
"main": "dist/index.js",
"exports": {
".": "./dist/index.js"
Expand All @@ -12,7 +12,6 @@
"dist"
],
"scripts": {
"postinstall": "npm install -g @salla.sa/cli",
"typecheck": "tsc --noEmit",
"test": "vitest run",
"test:watch": "vitest",
Expand All @@ -22,9 +21,11 @@
"engines": {
"node": ">=20.19.0"
},
"dependencies": {
"@salla.sa/cli": "^3.2.30"
},
"devDependencies": {
"@salla.sa/cli": "^3.2.30",
"@salla.sa/app-functions-types": "^0.3.0",
"@salla.sa/app-functions-types": "^0.5.0",
"@eslint/js": "^10.0.1",
"eslint": "^9.39.2",
"eslint-config-prettier": "^10.1.8",
Expand Down
24 changes: 24 additions & 0 deletions src/functions/custom-event-sync.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import type { FunctionResponse, SallaCustomEvent } from '@salla.sa/app-functions-types';

/**
* Handler for the `custom.event.sync` event.
*
* Every handler follows the same contract: it receives the typed event
* `context` (the custom event lives at `context.payload.data`) and returns a
* `FunctionResponse` — either a success or an error. Handlers may also be
* `async` and return a `Promise<FunctionResponse>`.
*/
export const customEventSync = (context: SallaCustomEvent): FunctionResponse => {
const eventData = context.payload.data;

console.log(`Custom event received with data: ${JSON.stringify(eventData)}`);

// Do your work here — call an API, enqueue a job, enrich the order, …

return {
success: true,
status: 200,
message: `Custom event invoked successfully.`,
data: { foo: 'bar' }
};
};
4 changes: 3 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
* just the handlers this map points at.
*/
import type { DefineEvents } from '@salla.sa/app-functions-types';
import { customEventSync } from './functions/custom-event-sync';
import { customerLogin } from './functions/customer-login';
import { orderCreated } from './functions/order-created';

Expand All @@ -33,7 +34,8 @@ const defineEvents: DefineEvents = (events) => events;
*/
const events = defineEvents({
'order.created': orderCreated,
'customer.login': customerLogin
'customer.login': customerLogin,
'custom.event.sync': customEventSync
});

// The Salla runtime imports this default export and dispatches every event to its handler.
Expand Down
10 changes: 5 additions & 5 deletions test/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import events from '../src';
/*
* These tests exercise the handlers exactly the way the platform does: they
* look each handler up in the exported `events` map and call it with a context
* object. Use them as a template — copy a block, swap in your event, and assert
* object. Use them as a starter kit — copy a block, swap in your event, and assert
* on the response your handler returns.
*
* The tricky part of testing handlers is that the real webhook payloads have
Expand All @@ -22,10 +22,10 @@ type CustomerData = Customer['payload']['data'];
* the fields it DOES provide are still checked against the real payload types. */
type DeepPartial<T> = {
[K in keyof T]?: T[K] extends (infer U)[]
? DeepPartial<U>[]
: T[K] extends object
? DeepPartial<T[K]>
: T[K];
? DeepPartial<U>[]
: T[K] extends object
? DeepPartial<T[K]>
: T[K];
};

/** Confines the "fill in the fields I didn't bother to set" cast to one spot,
Expand Down