@kmlckj/licos-platform-sdk 0.6.5 → 0.6.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -5,36 +5,62 @@ LICOS platform SDK for server-side project runtime code.
5
5
  ## Runtime Configuration
6
6
 
7
7
  Server-side helpers call platform Studio runtime APIs. Project code does not
8
- pass API base URLs, project IDs, tokens, or environment scopes. The SDK loads
9
- identity from runtime environment variables injected by LICOS. Authentication
10
- is resolved automatically by the runtime:
11
-
12
- - `LICOS_PLATFORM_API_BASE_URL`
13
- - `LICOS_PROJECT_ID` or `AGENT_PROJECT_ID`
14
- - `LICOS_WORKSPACE_ID` or `AGENT_WORKSPACE_ID`
15
- - `LICOS_USER_ID` or `AGENT_USER_ID`
16
- - `LICOS_PROJECT_ENV`, mapped internally to `dev` or `prod`
17
-
18
- ## Database
8
+ pass API base URLs, project IDs, tokens, or environment scopes. The SDK loads
9
+ identity from runtime environment variables injected by LICOS. Authentication
10
+ is resolved automatically by the runtime:
19
11
 
20
- Database CRUD helpers call the runtime database data plane only. Tooling helpers
21
- can fetch platform schema metadata for ORM export. The SDK does not expose
22
- service deletion APIs.
12
+ - `LICOS_PLATFORM_API_BASE_URL`
13
+ - `LICOS_PROJECT_ID` or `AGENT_PROJECT_ID`
14
+ - `LICOS_WORKSPACE_ID` or `AGENT_WORKSPACE_ID`
15
+ - `LICOS_USER_ID` or `AGENT_USER_ID`
16
+ - `LICOS_PROJECT_ENV`, mapped internally to `dev` or `prod`
23
17
 
24
- ```js
25
- import { database } from '@kmlckj/licos-platform-sdk';
18
+ ## Database
26
19
 
27
- const rows = await database
20
+ Database CRUD helpers call the runtime database data plane only. Tooling helpers
21
+ can fetch platform schema metadata for ORM export. The SDK does not expose
22
+ service deletion APIs.
23
+
24
+ `database.table(name)` is a query builder. Use it for `select` queries only.
25
+
26
+ ```js
27
+ import { database } from '@kmlckj/licos-platform-sdk';
28
+
29
+ const rows = await database
28
30
  .table('todos')
29
31
  .select('id', 'title')
30
32
  .eq('done', false)
31
33
  .order('created_at', { desc: true })
32
- .limit(10)
33
- .execute();
34
- ```
35
-
36
- ORM export is a tooling helper. It fetches platform schema metadata and returns
37
- source text; it does not use direct database credentials.
34
+ .limit(10)
35
+ .execute();
36
+ ```
37
+
38
+ Use top-level helpers for mutations:
39
+
40
+ ```js
41
+ import { database } from '@kmlckj/licos-platform-sdk';
42
+
43
+ const inserted = await database.insert('todos', {
44
+ row: { title: 'Call customer', done: false },
45
+ returning: true,
46
+ });
47
+
48
+ await database.updateRows('todos', {
49
+ filters: [{ field: 'id', op: 'eq', value: inserted.data?.[0]?.id }],
50
+ values: { done: true },
51
+ });
52
+
53
+ await database.deleteRows('todos', {
54
+ filters: [{ field: 'done', op: 'eq', value: true }],
55
+ });
56
+ ```
57
+
58
+ Do not call `.table('todos').insert(...)`, `.table('todos').updateRows(...)`,
59
+ or `.table('todos').deleteRows(...)`; those methods do not exist on the query
60
+ builder.
61
+
62
+ ORM export is a tooling helper. It fetches platform schema metadata and returns
63
+ source text; it does not use direct database credentials.
38
64
 
39
65
  ```js
40
66
  import { database } from '@kmlckj/licos-platform-sdk';
@@ -42,6 +68,22 @@ import { database } from '@kmlckj/licos-platform-sdk';
42
68
  const source = await database.exportOrm({ language: 'typescript', orm: 'drizzle' });
43
69
  ```
44
70
 
71
+ Studio project database management is exposed through `studioDatabase` for
72
+ server-side tooling flows. Use it for tables, rows, controlled SQL, migrations,
73
+ sync, and backup. Do not import it into browser/client bundles. Do not put
74
+ schema creation or migration logic in normal project runtime request handlers;
75
+ run those operations from LICOS agent/tooling flows before the app starts.
76
+
77
+ ```js
78
+ import { studioDatabase } from '@kmlckj/licos-platform-sdk';
79
+
80
+ await studioDatabase.createTable('users', {
81
+ columns: [{ name: 'email', type: 'text', nullable: false }],
82
+ });
83
+
84
+ const schema = await studioDatabase.getSchema({ environment: 'dev' });
85
+ ```
86
+
45
87
  ## Object Storage
46
88
 
47
89
  ```js
@@ -56,3 +98,26 @@ const link = await storage.shareUrl(file.id);
56
98
 
57
99
  The browser entry does not export object storage helpers because runtime tokens
58
100
  must not be bundled into public frontend code.
101
+
102
+ ## Knowledge
103
+
104
+ Knowledge helpers import project documents and run semantic retrieval through
105
+ the LICOS Knowledge API. Search without dataset filters retrieves from all
106
+ accessible datasets. Use dataset IDs or names only when the user explicitly
107
+ targets a specific knowledge base.
108
+
109
+ ```js
110
+ import { knowledge } from '@kmlckj/licos-platform-sdk';
111
+
112
+ await knowledge.addText('FAQ content', {
113
+ datasetName: 'project_docs',
114
+ name: 'faq.txt',
115
+ });
116
+
117
+ const results = await knowledge.search('How do I reset my password?', {
118
+ topK: 5,
119
+ });
120
+ ```
121
+
122
+ The browser entry does not export knowledge helpers because runtime tokens must
123
+ not be bundled into public frontend code.
@@ -0,0 +1 @@
1
+ export{PlatformSdkError,ConfigurationError,ApiError}from"./shared.js";
@@ -0,0 +1 @@
1
+ import{ApiError as e}from"./shared.js";import{authHeaders as t,refreshRuntimeConfig as r,runtimeConfig as n,shouldRefreshUserToken as i}from"./runtime.js";async function s(){return n()}function o(e,t){return`${e.baseUrl}/api/v1/studio/runtime/database/projects/${encodeURIComponent(e.projectId)}${t}`}function a(e,t){return`${e.baseUrl}/api/v1/studio/control/database/projects/${encodeURIComponent(e.projectId)}${t}`}function l(e){if(null!=e)return"string"==typeof e?e.split(",").map(e=>e.trim()).filter(Boolean):Array.from(e).map(e=>String(e))}async function u(t){const r=await t.text(),n=r?JSON.parse(r):null;if(!t.ok)throw new e(r||`platform database API returned ${t.status}`,{status:t.status,details:n});if(!n||"object"!=typeof n)return n;if(void 0!==n.code&&0!==n.code||!1===n.success)throw new e(n.message||"platform database API failed",{status:t.status,code:"number"==typeof n.code?n.code:void 0,details:n});return n.data}async function c(n,a){let l=await s();const c={environment:l.environment,...(d=a,Object.fromEntries(Object.entries(d).filter(([,e])=>null!=e)))};var d;for(let e=0;e<2;e+=1)try{const e=await fetch(o(l,n),{method:"POST",headers:t(l),body:JSON.stringify(c)});return await u(e)}catch(t){if(0===e&&i(t)){l=await r(l);continue}throw t}throw new e("platform database API failed")}export async function query(e,t={}){return c("/query",{table:e,select:l(t.select),filters:t.filters?.length?t.filters:void 0,orderBy:t.orderBy?.length?t.orderBy:void 0,range:t.range,limit:t.limit,offset:t.offset,count:t.count,head:t.head})}export async function single(e,t={}){return c("/single",{table:e,select:l(t.select),filters:t.filters?.length?t.filters:void 0,orderBy:t.orderBy?.length?t.orderBy:void 0,mode:t.maybe?"maybe_single":"single"})}export async function maybeSingle(e,t={}){return single(e,{...t,maybe:!0})}export async function aggregate(e,t,r={}){return c("/aggregate",{table:e,filters:r.filters?.length?r.filters:void 0,aggregate:t,field:r.field,groupBy:r.groupBy?.length?r.groupBy:void 0})}export async function insert(e,t={}){return c("/insert",{table:e,row:t.row,rows:t.rows,returning:t.returning??!0})}export async function updateRows(e,t={}){return c("/update",{table:e,values:t.values,filters:t.filters?.length?t.filters:void 0,updates:t.updates?.length?t.updates:void 0,returning:t.returning??!0})}export async function deleteRows(e,t={}){return c("/delete",{table:e,filters:t.filters?.length?t.filters:void 0,deletes:t.deletes?.length?t.deletes:void 0,returning:t.returning??!0})}export async function upsert(e,t={}){return c("/upsert",{table:e,row:t.row,rows:t.rows,conflictKeys:t.conflictKeys?.length?t.conflictKeys:void 0,returning:t.returning??!0})}export async function transaction(e){const t=await s();return c("/transaction",{operations:e.map(e=>({type:e.type,request:{...e.request,environment:t.environment}}))})}export async function rpc(e,t={}){return c(`/rpc/${encodeURIComponent(e)}`,{args:t})}export async function getSchema(){return async function(n,o={}){let l=await s();for(let e=0;e<2;e+=1){const s=new URL(a(l,n));for(const[e,t]of Object.entries({environment:l.environment,...o}))null!=t&&s.searchParams.set(e,String(t));try{const e=await fetch(s,{method:"GET",headers:t(l)});return await u(e)}catch(t){if(0===e&&i(t)){l=await r(l);continue}throw t}}throw new e("platform database control API failed")}("/schema")}export function defaultOrm(e){return"typescript"===p(e)?"drizzle":"sqlalchemy"}export function generateOrm(e,t={}){const r=p(t.language),n=function(e,t){const r=String(t||defaultOrm(e)).trim().toLowerCase();if("typescript"===e&&"drizzle"!==r)throw new Error("typescript ORM export only supports drizzle");if("python"===e&&"sqlalchemy"!==r)throw new Error("python ORM export only supports sqlalchemy");return r}(r,t.orm);if("typescript"===r&&"drizzle"===n)return function(e){const t=m(e);if(!t.length)return"// Generated by licos-platform database export-orm.\n// No tables found in schema.\n";const r=new Set;let n=!1;const i=new Set,s=new Set,o=[...new Set(t.map(e=>String(e.schema||"public")).filter(e=>"public"!==e))].sort(),a=Object.fromEntries(o.map(e=>[e,g(`${e}_schema`)]));o.length&&r.add("pgSchema");const l=[],u=[];for(const e of t){const t=String(e.schema||"public"),o=String(e.name||"table"),c=w(g(o),i,"public"!==t?g(t):void 0),d=w(y(o),s,"public"!==t?y(t):void 0),p="public"===t?"pgTable":`${a[t]}.table`;"public"===t&&r.add("pgTable");const m=new Set,h=f(e).map(e=>{const t=w(g(e.name||"column"),m),{expression:i,imports:s,usesSql:o}=v(e);return s.forEach(e=>r.add(e)),n=n||o,` ${t}: ${i},`});h.length||h.push(" // No columns found."),l.push(`export const ${c} = ${p}(${_(o)}, {\n${h.join("\n")}\n});`),u.push(`export type ${d} = typeof ${c}.$inferSelect;`),u.push(`export type New${d} = typeof ${c}.$inferInsert;`)}const c=["// Generated by licos-platform database export-orm.",""];n&&c.push("import { sql } from 'drizzle-orm';"),c.push(`import { ${[...r].sort().join(", ")} } from 'drizzle-orm/pg-core';`),c.push("");for(const e of o)c.push(`const ${a[e]} = pgSchema(${_(e)});`);return o.length&&c.push(""),c.push(...l,"",...u),`${c.join("\n").trimEnd()}\n`}(e);if("python"===r&&"sqlalchemy"===n)return function(e){const t=m(e);if(!t.length)return"# Generated by licos-platform database export-orm.\n# No tables found in schema.\n";const r=new Set,n=new Set,i=new Set;let s=!1,o=!1;const a=new Set,l=[];for(const e of t){const t=String(e.schema||"public"),u=String(e.name||"table"),c=w(y(u),a,"public"!==t?y(t):void 0),d=new Set,p=[` __tablename__ = ${_(u)}`];"public"!==t&&p.push(` __table_args__ = {"schema": ${_(t)}}`);for(const t of f(e)){const e=x(t,w(b(t.name||"column"),d));e.imports.forEach(e=>r.add(e)),e.typingImports.forEach(e=>n.add(e)),e.datetimeImports.forEach(e=>i.add(e)),s=s||e.needsDecimal,o=o||e.needsAny,p.push(e.line)}p.length===("public"===t?1:2)&&p.push(" pass"),l.push(`class ${c}(Base):\n${p.join("\n")}`)}const u=["# Generated by licos-platform database export-orm.","from __future__ import annotations",""];return i.size&&u.push(`from datetime import ${[...i].sort().join(", ")}`),s&&u.push("from decimal import Decimal"),(n.size||o)&&u.push(`from typing import ${[...n,...o?["Any"]:[]].sort().join(", ")}`),(i.size||s||n.size||o)&&u.push(""),u.push(`from sqlalchemy import ${[...r].sort().join(", ")}`),u.push("from sqlalchemy.orm import Mapped, mapped_column"),u.push(""),u.push("from .base import Base"),u.push(""),u.push(...l),`${u.join("\n\n").trimEnd()}\n`}(e);throw new Error(`unsupported ORM export target: ${t.language}/${t.orm??"default"}`)}export async function exportOrm(e={}){return generateOrm(await getSchema(),e)}export function table(e){return new d(e)}class d{constructor(e){this.name=e,this._select=void 0,this._filters=[],this._orderBy=[],this._range=void 0,this._limit=void 0,this._offset=void 0,this._count=void 0,this._head=void 0}select(...e){return this._select=1===e.length&&e[0].includes(",")?l(e[0]):e,this}filter(e,t,r){return this._filters.push({field:e,op:t,value:r}),this}eq(e,t){return this.filter(e,"eq",t)}neq(e,t){return this.filter(e,"neq",t)}gt(e,t){return this.filter(e,"gt",t)}gte(e,t){return this.filter(e,"gte",t)}lt(e,t){return this.filter(e,"lt",t)}lte(e,t){return this.filter(e,"lte",t)}in(e,t){return this.filter(e,"in",t)}notIn(e,t){return this.filter(e,"not_in",t)}isNull(e){return this.filter(e,"is_null")}isNotNull(e){return this.filter(e,"is_not_null")}like(e,t){return this.filter(e,"like",t)}ilike(e,t){return this.filter(e,"ilike",t)}order(e,t={}){return this._orderBy.push({field:e,direction:t.desc?"desc":"asc"}),this}range(e,t){return this._range={from:e,to:t},this}limit(e){return this._limit=e,this}offset(e){return this._offset=e,this}withCount(e={}){return this._count=!0,this._head=Boolean(e.head),this}execute(){return query(this.name,{select:this._select,filters:this._filters,orderBy:this._orderBy,range:this._range,limit:this._limit,offset:this._offset,count:this._count,head:this._head})}single(){return single(this.name,{select:this._select,filters:this._filters,orderBy:this._orderBy})}maybeSingle(){return maybeSingle(this.name,{select:this._select,filters:this._filters,orderBy:this._orderBy})}}function p(e){const t={ts:"typescript",node:"typescript",nodejs:"typescript",js:"typescript",javascript:"typescript",py:"python"}[String(e||"").trim().toLowerCase()]||String(e||"").trim().toLowerCase();if(!["typescript","python"].includes(t))throw new Error("language must be typescript or python");return t}function m(e){return Array.isArray(e?.tables)?e.tables:[]}function f(e){return Array.isArray(e?.columns)?e.columns:[]}function h(e){const t=String(e||"value").match(/[A-Za-z0-9]+/g);return t?.length?t:["value"]}function g(e){const t=h(e);let r=t[0].toLowerCase()+t.slice(1).map(e=>e[0].toUpperCase()+e.slice(1).toLowerCase()).join("");return/^[0-9]/.test(r)&&(r=`_${r}`),j.has(r)&&(r=`${r}_`),r}function y(e){let t=h(e).map(e=>e[0].toUpperCase()+e.slice(1).toLowerCase()).join("");return/^[0-9]/.test(t)&&(t=`_${t}`),t}function b(e){let t=h(e).map(e=>e.toLowerCase()).join("_");return/^[0-9]/.test(t)&&(t=`_${t}`),B.has(t)&&(t=`${t}_`),t}function w(e,t,r){let n=e;t.has(n)&&r&&(n=`${r}${e[0].toUpperCase()}${e.slice(1)}`);const i=n;let s=2;for(;t.has(n);)n=`${i}${s}`,s+=1;return t.add(n),n}function _(e){return JSON.stringify(String(e))}function $(e){return String(e?.type||"").replace(/\s+/g," ").trim().toLowerCase()}function S(e){return void 0!==e?.defaultValue&&null!==e.defaultValue&&""!==String(e.defaultValue).trim()}function v(e){const t=$(e),r=new Set;let n="text";const i=[_(e.name||"column")];"uuid"===t?n="uuid":["integer","int","int4","serial"].includes(t)?n="integer":["bigint","int8","bigserial"].includes(t)?(n="bigint",i.push("{ mode: 'number' }")):["smallint","int2","smallserial"].includes(t)?n="smallint":["boolean","bool"].includes(t)?n="boolean":["character varying","varchar","character","char"].includes(t)?n="varchar":["timestamp with time zone","timestamptz"].includes(t)?(n="timestamp",i.push("{ withTimezone: true }")):["timestamp without time zone","timestamp"].includes(t)?n="timestamp":"date"===t?n="date":t.startsWith("time")?n="time":["numeric","decimal"].includes(t)?n="numeric":["double precision","float8"].includes(t)?n="doublePrecision":["real","float4"].includes(t)?n="real":"json"===t?n="json":"jsonb"===t&&(n="jsonb"),r.add(n);let s=`${n}(${i.join(", ")})`;e.primaryKey?s+=".primaryKey()":!1===e.nullable&&(s+=".notNull()");let o=!1;return S(e)&&(s+=`.default(sql\`${String(e.defaultValue).replace(/`/g,"\\`").replace(/\$\{/g,"\\${")}\`)`,o=!0),{expression:s,imports:r,usesSql:o}}function x(e,t){const r=$(e),n=new Set,i=new Set,s=new Set;let o=!1,a=!1,l="Text",u="str";"uuid"===r?(l="String(36)",n.add("String")):["integer","int","int4","serial","smallint","int2","smallserial"].includes(r)?(l="Integer",u="int",n.add("Integer")):["bigint","int8","bigserial"].includes(r)?(l="BigInteger",u="int",n.add("BigInteger")):["boolean","bool"].includes(r)?(l="Boolean",u="bool",n.add("Boolean")):["character varying","varchar","character","char"].includes(r)?(l="String",n.add("String")):["timestamp with time zone","timestamptz"].includes(r)?(l="DateTime(timezone=True)",u="datetime",n.add("DateTime"),s.add("datetime")):["timestamp without time zone","timestamp"].includes(r)?(l="DateTime",u="datetime",n.add("DateTime"),s.add("datetime")):"date"===r?(l="Date",u="date",n.add("Date"),s.add("date")):r.startsWith("time")?(l="Time",u="time",n.add("Time"),s.add("time")):["numeric","decimal"].includes(r)?(l="Numeric",u="Decimal",n.add("Numeric"),o=!0):["double precision","float8","real","float4"].includes(r)?(l="Float",u="float",n.add("Float")):["json","jsonb"].includes(r)?(l="JSON",u="dict[str, Any]",n.add("JSON"),a=!0):n.add("Text"),!0!==e.nullable||e.primaryKey||(u=`Optional[${u}]`,i.add("Optional"));const c=[];return t!==e.name&&c.push(_(e.name||t)),c.push(l),e.primaryKey&&c.push("primary_key=True"),void 0!==e.nullable&&null!==e.nullable&&c.push("nullable="+(Boolean(e.nullable)?"True":"False")),S(e)&&(n.add("text"),c.push(`server_default=text(${_(e.defaultValue)})`)),{line:` ${t}: Mapped[${u}] = mapped_column(${c.join(", ")})`,imports:n,typingImports:i,datetimeImports:s,needsDecimal:o,needsAny:a}}const j=new Set(["break","case","catch","class","const","continue","debugger","default","delete","do","else","export","extends","finally","for","function","if","import","in","instanceof","new","return","super","switch","this","throw","try","typeof","var","void","while","with","yield"]),B=new Set(["False","None","True","and","as","assert","async","await","break","class","continue","def","del","elif","else","except","finally","for","from","global","if","import","in","is","lambda","nonlocal","not","or","pass","raise","return","try","while","with","yield"]);export const database={query:query,single:single,maybeSingle:maybeSingle,aggregate:aggregate,insert:insert,updateRows:updateRows,deleteRows:deleteRows,upsert:upsert,transaction:transaction,rpc:rpc,getSchema:getSchema,defaultOrm:defaultOrm,generateOrm:generateOrm,exportOrm:exportOrm,table:table};