chore: import upstream snapshot with attribution
CI / Deep Native Runtime Cases (1/6) (push) Has been skipped
CI / Native Preflight (push) Failing after 1s
CI / Native Runtime Cases (1/2) (push) Failing after 0s
CI / Native Runtime Cases (2/2) (push) Failing after 1s
CI / Native Metadata Reports (push) Failing after 0s
CI / Native Direct Backend Artifacts (push) Failing after 0s
CI / Native Sanitizer Smoke (push) Failing after 1s
CI / Command Contract Snapshots (push) Failing after 1s
CI / Deep Conformance Suite (push) Has been skipped
CI / Graph Build Perf (push) Failing after 1s
CI / Deep Native Preflight (push) Has been skipped
CI / Deep Native Runtime Cases (2/6) (push) Has been skipped
CI / Deep Native Runtime Cases (3/6) (push) Has been skipped
CI / Conformance Suite (push) Failing after 1s
CI / Workspace Checks (push) Failing after 0s
CI / Deep Native Runtime Cases (5/6) (push) Has been skipped
CI / Deep Native Runtime Cases (6/6) (push) Has been skipped
CI / Deep Native Runtime Cases (4/6) (push) Has been skipped
CI / Deep Graph Build Perf (push) Has been skipped
CI / Deep Native Runtime Cases (1/6) (push) Has been skipped
CI / Native Preflight (push) Failing after 1s
CI / Native Runtime Cases (1/2) (push) Failing after 0s
CI / Native Runtime Cases (2/2) (push) Failing after 1s
CI / Native Metadata Reports (push) Failing after 0s
CI / Native Direct Backend Artifacts (push) Failing after 0s
CI / Native Sanitizer Smoke (push) Failing after 1s
CI / Command Contract Snapshots (push) Failing after 1s
CI / Deep Conformance Suite (push) Has been skipped
CI / Graph Build Perf (push) Failing after 1s
CI / Deep Native Preflight (push) Has been skipped
CI / Deep Native Runtime Cases (2/6) (push) Has been skipped
CI / Deep Native Runtime Cases (3/6) (push) Has been skipped
CI / Conformance Suite (push) Failing after 1s
CI / Workspace Checks (push) Failing after 0s
CI / Deep Native Runtime Cases (5/6) (push) Has been skipped
CI / Deep Native Runtime Cases (6/6) (push) Has been skipped
CI / Deep Native Runtime Cases (4/6) (push) Has been skipped
CI / Deep Graph Build Perf (push) Has been skipped
This commit is contained in:
@@ -0,0 +1,30 @@
|
||||
use http_util
|
||||
|
||||
pub fn listAccounts(request: Span<u8>, response: MutSpan<u8>) -> Maybe<Span<u8>> {
|
||||
if tenantOk(request) {
|
||||
return jsonResponse(response, 200_u16, "{\"accounts\":[{\"id\":1,\"name\":\"Acme\",\"owner\":\"Ada\"},{\"id\":2,\"name\":\"Globex\",\"owner\":\"Lin\"}],\"next\":null}")
|
||||
}
|
||||
return badRequest(response, "tenant")
|
||||
}
|
||||
|
||||
pub fn createAccount(request: Span<u8>, response: MutSpan<u8>) -> Maybe<Span<u8>> {
|
||||
if bodyIsJson(request, 256) && bodyHasU32(request, "owner_id", 256) {
|
||||
return jsonResponse(response, 201_u16, "{\"account\":{\"id\":3,\"name\":\"New account\",\"owner_id\":9},\"created\":true}")
|
||||
}
|
||||
return badRequest(response, "json")
|
||||
}
|
||||
|
||||
pub fn readAccount(response: MutSpan<u8>) -> Maybe<Span<u8>> {
|
||||
return jsonResponse(response, 200_u16, "{\"account\":{\"id\":1,\"name\":\"Acme\",\"stage\":\"customer\",\"owner\":\"Ada\"}}")
|
||||
}
|
||||
|
||||
pub fn updateAccount(request: Span<u8>, response: MutSpan<u8>) -> Maybe<Span<u8>> {
|
||||
if bodyIsJson(request, 256) {
|
||||
return jsonResponse(response, 200_u16, "{\"account\":{\"id\":1,\"name\":\"Acme Updated\",\"stage\":\"customer\"},\"updated\":true}")
|
||||
}
|
||||
return badRequest(response, "json")
|
||||
}
|
||||
|
||||
pub fn deleteAccount(response: MutSpan<u8>) -> Maybe<Span<u8>> {
|
||||
return jsonResponse(response, 200_u16, "{\"account\":{\"id\":1},\"deleted\":true}")
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
use http_util
|
||||
|
||||
pub fn listActivities(request: Span<u8>, response: MutSpan<u8>) -> Maybe<Span<u8>> {
|
||||
return jsonResponse(response, 200_u16, "{\"activities\":[{\"id\":77,\"type\":\"call\",\"account_id\":1},{\"id\":78,\"type\":\"email\",\"account_id\":1}]}")
|
||||
}
|
||||
|
||||
pub fn createActivity(request: Span<u8>, response: MutSpan<u8>) -> Maybe<Span<u8>> {
|
||||
if bodyIsJson(request, 256) && bodyHasU32(request, "account_id", 256) {
|
||||
return jsonResponse(response, 201_u16, "{\"activity\":{\"id\":102,\"kind\":\"note\",\"account_id\":1},\"created\":true}")
|
||||
}
|
||||
return badRequest(response, "json")
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
use http_util
|
||||
|
||||
pub fn listContacts(request: Span<u8>, response: MutSpan<u8>) -> Maybe<Span<u8>> {
|
||||
if tenantOk(request) {
|
||||
return jsonResponse(response, 200_u16, "{\"contacts\":[{\"id\":7,\"name\":\"Grace Hopper\",\"account_id\":1},{\"id\":8,\"name\":\"Katherine Johnson\",\"account_id\":2}]}")
|
||||
}
|
||||
return badRequest(response, "tenant")
|
||||
}
|
||||
|
||||
pub fn createContact(request: Span<u8>, response: MutSpan<u8>) -> Maybe<Span<u8>> {
|
||||
if bodyIsJson(request, 256) && bodyHasU32(request, "account_id", 256) {
|
||||
return jsonResponse(response, 201_u16, "{\"contact\":{\"id\":9,\"name\":\"New contact\",\"account_id\":1},\"created\":true}")
|
||||
}
|
||||
return badRequest(response, "json")
|
||||
}
|
||||
|
||||
pub fn readContact(response: MutSpan<u8>) -> Maybe<Span<u8>> {
|
||||
return jsonResponse(response, 200_u16, "{\"contact\":{\"id\":7,\"name\":\"Grace Hopper\",\"email\":\"grace@example.com\",\"account_id\":1}}")
|
||||
}
|
||||
|
||||
pub fn updateContact(request: Span<u8>, response: MutSpan<u8>) -> Maybe<Span<u8>> {
|
||||
if bodyIsJson(request, 256) {
|
||||
return jsonResponse(response, 200_u16, "{\"contact\":{\"id\":7,\"name\":\"Grace Hopper\",\"email\":\"updated@example.com\"},\"updated\":true}")
|
||||
}
|
||||
return badRequest(response, "json")
|
||||
}
|
||||
|
||||
pub fn deleteContact(response: MutSpan<u8>) -> Maybe<Span<u8>> {
|
||||
return jsonResponse(response, 200_u16, "{\"contact\":{\"id\":7},\"deleted\":true}")
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
use http_util
|
||||
|
||||
pub fn listDeals(request: Span<u8>, response: MutSpan<u8>) -> Maybe<Span<u8>> {
|
||||
if tenantOk(request) {
|
||||
return jsonResponse(response, 200_u16, "{\"deals\":[{\"id\":42,\"name\":\"Expansion\",\"amount\":120000},{\"id\":43,\"name\":\"Renewal\",\"amount\":45000}]}")
|
||||
}
|
||||
return badRequest(response, "tenant")
|
||||
}
|
||||
|
||||
pub fn createDeal(request: Span<u8>, response: MutSpan<u8>) -> Maybe<Span<u8>> {
|
||||
if bodyIsJson(request, 256) && bodyHasU32(request, "account_id", 256) {
|
||||
return jsonResponse(response, 201_u16, "{\"deal\":{\"id\":44,\"name\":\"New deal\",\"account_id\":1,\"amount\":10000},\"created\":true}")
|
||||
}
|
||||
return badRequest(response, "json")
|
||||
}
|
||||
|
||||
pub fn readDeal(response: MutSpan<u8>) -> Maybe<Span<u8>> {
|
||||
return jsonResponse(response, 200_u16, "{\"deal\":{\"id\":42,\"name\":\"Expansion\",\"stage\":\"proposal\",\"amount\":120000}}")
|
||||
}
|
||||
|
||||
pub fn updateDeal(request: Span<u8>, response: MutSpan<u8>) -> Maybe<Span<u8>> {
|
||||
if bodyIsJson(request, 256) {
|
||||
return jsonResponse(response, 200_u16, "{\"deal\":{\"id\":42,\"stage\":\"won\",\"amount\":120000},\"updated\":true}")
|
||||
}
|
||||
return badRequest(response, "json")
|
||||
}
|
||||
|
||||
pub fn deleteDeal(response: MutSpan<u8>) -> Maybe<Span<u8>> {
|
||||
return jsonResponse(response, 200_u16, "{\"deal\":{\"id\":42},\"deleted\":true}")
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
pub fn jsonResponse(response: MutSpan<u8>, status: u16, body: Span<u8>) -> Maybe<Span<u8>> {
|
||||
return std.http.writeJsonResponse(response, status, body)
|
||||
}
|
||||
|
||||
pub fn notFound(response: MutSpan<u8>) -> Maybe<Span<u8>> {
|
||||
return std.http.writeJsonNotFound(response, "{\"error\":\"not_found\",\"resource\":\"crm\"}")
|
||||
}
|
||||
|
||||
pub fn methodNotAllowed(response: MutSpan<u8>) -> Maybe<Span<u8>> {
|
||||
return std.http.writeJsonMethodNotAllowed(response, "{\"error\":\"method_not_allowed\"}")
|
||||
}
|
||||
|
||||
pub fn badRequest(response: MutSpan<u8>, field: Span<u8>) -> Maybe<Span<u8>> {
|
||||
if std.mem.eql(field, "tenant") {
|
||||
return std.http.writeJsonBadRequest(response, "{\"error\":\"bad_request\",\"field\":\"tenant\"}")
|
||||
}
|
||||
if std.mem.eql(field, "json") {
|
||||
return std.http.writeJsonBadRequest(response, "{\"error\":\"bad_request\",\"field\":\"body\"}")
|
||||
}
|
||||
if std.mem.eql(field, "id") {
|
||||
return std.http.writeJsonBadRequest(response, "{\"error\":\"bad_request\",\"field\":\"id\"}")
|
||||
}
|
||||
return std.http.writeJsonBadRequest(response, "{\"error\":\"bad_request\"}")
|
||||
}
|
||||
|
||||
pub fn tenantOk(request: Span<u8>) -> Bool {
|
||||
let tenant: Maybe<Span<u8>> = std.http.requestQueryValue(request, "tenant")
|
||||
return tenant.has
|
||||
}
|
||||
|
||||
pub fn bodyIsJson(request: Span<u8>, max_bytes: usize) -> Bool {
|
||||
let body: Maybe<Span<u8>> = std.http.requestJsonBodyWithin(request, max_bytes)
|
||||
return body.has
|
||||
}
|
||||
|
||||
pub fn bodyHasU32(request: Span<u8>, field: Span<u8>, max_bytes: usize) -> Bool {
|
||||
let body: Maybe<Span<u8>> = std.http.requestJsonBodyWithin(request, max_bytes)
|
||||
if !body.has {
|
||||
return false
|
||||
}
|
||||
let value: Maybe<u32> = std.json.u32(body.value, field)
|
||||
return value.has
|
||||
}
|
||||
|
||||
pub fn responseBody(output: Span<u8>) -> Span<u8> {
|
||||
let body: Maybe<Span<u8>> = std.http.responseBodyBytes(output)
|
||||
if body.has {
|
||||
return body.value
|
||||
}
|
||||
let end: usize = std.mem.len(output)
|
||||
return output[end..]
|
||||
}
|
||||
|
||||
pub fn responseHasStatus(output: Span<u8>, status: Span<u8>) -> Bool {
|
||||
return std.str.contains(output, status)
|
||||
}
|
||||
|
||||
pub fn responseBodyEquals(output: Span<u8>, expected: Span<u8>) -> Bool {
|
||||
return std.mem.eql(responseBody(output), expected)
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
use router
|
||||
|
||||
pub fn main(world: World) -> Void raises {
|
||||
let maybe_request: Maybe<String> = std.args.get(1)
|
||||
if !maybe_request.has {
|
||||
check world.err.write("usage: pass one HTTP request envelope\n")
|
||||
return
|
||||
}
|
||||
var response: [1024]u8 = [0_u8; 1024]
|
||||
let output: Maybe<Span<u8>> = handleCrm(std.mem.span(maybe_request.value), response)
|
||||
if output.has {
|
||||
check world.out.write(output.value)
|
||||
return
|
||||
}
|
||||
check world.err.write("crm api router failed\n")
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
use accounts
|
||||
|
||||
use activities
|
||||
|
||||
use contacts
|
||||
|
||||
use deals
|
||||
|
||||
use http_util
|
||||
|
||||
use search
|
||||
|
||||
pub fn handleCrm(request: Span<u8>, response: MutSpan<u8>) -> Maybe<Span<u8>> {
|
||||
let method: Maybe<Span<u8>> = std.http.requestMethodName(request)
|
||||
let path: Maybe<Span<u8>> = std.http.requestPath(request)
|
||||
if !method.has {
|
||||
return badRequest(response, "json")
|
||||
}
|
||||
if !path.has {
|
||||
return badRequest(response, "json")
|
||||
}
|
||||
if std.http.requestIsGet(request, "/health") {
|
||||
return jsonResponse(response, 200_u16, "{\"ok\":true,\"service\":\"crm\"}")
|
||||
}
|
||||
if std.http.requestIsGet(request, "/crm/accounts") {
|
||||
return listAccounts(request, response)
|
||||
}
|
||||
if std.http.requestIsPost(request, "/crm/accounts") {
|
||||
return createAccount(request, response)
|
||||
}
|
||||
if std.http.requestIsGet(request, "/crm/accounts/1") {
|
||||
return readAccount(response)
|
||||
}
|
||||
if std.http.requestIsPost(request, "/crm/accounts/1/update") {
|
||||
return updateAccount(request, response)
|
||||
}
|
||||
if std.http.requestIsPost(request, "/crm/accounts/1/delete") {
|
||||
return deleteAccount(response)
|
||||
}
|
||||
if std.http.requestIsGet(request, "/crm/contacts") {
|
||||
return listContacts(request, response)
|
||||
}
|
||||
if std.http.requestIsPost(request, "/crm/contacts") {
|
||||
return createContact(request, response)
|
||||
}
|
||||
if std.http.requestIsGet(request, "/crm/contacts/7") {
|
||||
return readContact(response)
|
||||
}
|
||||
if std.http.requestIsPost(request, "/crm/contacts/7/update") {
|
||||
return updateContact(request, response)
|
||||
}
|
||||
if std.http.requestIsPost(request, "/crm/contacts/7/delete") {
|
||||
return deleteContact(response)
|
||||
}
|
||||
if std.http.requestIsGet(request, "/crm/deals") {
|
||||
return listDeals(request, response)
|
||||
}
|
||||
if std.http.requestIsPost(request, "/crm/deals") {
|
||||
return createDeal(request, response)
|
||||
}
|
||||
if std.http.requestIsGet(request, "/crm/deals/42") {
|
||||
return readDeal(response)
|
||||
}
|
||||
if std.http.requestIsPost(request, "/crm/deals/42/update") {
|
||||
return updateDeal(request, response)
|
||||
}
|
||||
if std.http.requestIsPost(request, "/crm/deals/42/delete") {
|
||||
return deleteDeal(response)
|
||||
}
|
||||
if std.http.requestIsGet(request, "/crm/activities") {
|
||||
return listActivities(request, response)
|
||||
}
|
||||
if std.http.requestIsPost(request, "/crm/activities") {
|
||||
return createActivity(request, response)
|
||||
}
|
||||
if std.http.requestIsGet(request, "/crm/search") {
|
||||
return searchCrm(request, response)
|
||||
}
|
||||
if std.http.requestMethodIs(request, "PUT") {
|
||||
return methodNotAllowed(response)
|
||||
}
|
||||
if std.http.requestMethodIs(request, "PATCH") {
|
||||
return methodNotAllowed(response)
|
||||
}
|
||||
if std.http.requestMethodIs(request, "DELETE") {
|
||||
return methodNotAllowed(response)
|
||||
}
|
||||
if std.http.requestMethodIs(request, "POST") {
|
||||
return methodNotAllowed(response)
|
||||
}
|
||||
return notFound(response)
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
use http_util
|
||||
|
||||
pub fn searchCrm(request: Span<u8>, response: MutSpan<u8>) -> Maybe<Span<u8>> {
|
||||
return jsonResponse(response, 200_u16, "{\"results\":[{\"type\":\"account\",\"id\":1,\"label\":\"Acme\"},{\"type\":\"deal\",\"id\":42,\"label\":\"Expansion\"}]}")
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,7 @@
|
||||
[package]
|
||||
name = "crm-api"
|
||||
version = "0.1.0"
|
||||
|
||||
[targets.cli]
|
||||
kind = "exe"
|
||||
main = "src/main.0"
|
||||
Reference in New Issue
Block a user