대시보드
Morit Plugin3. 화면과 사용자 경험

Morit Script 레퍼런스

Morit Script는 Runtime v3 화면에서 API 응답을 화면용 데이터로 바꾸는 작은 순수 함수 언어입니다. logic/*.morit 파일에 작성하고, SDK가 build할 때 AST로 컴파일해 패키지에 넣습니다. Host와 서버는 컴파일된 AST만 실행하며 파일·네트워크·credential·프로세스에 접근할 수 없습니다.

이 문서는 @morit/cli의 SDK 파서(morit-script.js)와 런타임(script-runtime.js) 기준입니다. 모듈 선언, computed_state, data source transform 연결은 Runtime v3와 Morit Script를 참고하세요.

예제

text
function cleanMenu(items) {
  return items.map(item => html.toText(item)).filter(item => item != "");
}

export function normalizeDay(input) {
  const days = input.days.map(day => ({
    date: day.date,
    lessons: day.lessons.map(lesson => ({
      period: lesson.period,
      label: string.from(lesson.period) + "교시"
    })),
    meals: day.meals.map(meal => ({ name: meal.name, menu: cleanMenu(meal.menu) }))
  }));
  return {days: days, lessonCount: days.reduce((count, day) => count + day.lessons.length, 0)};
}

export한 함수만 manifest의 logic_modules[].exports와 data source transform에서 부를 수 있고, 각 export에는 input_schema와 output_schema를 선언합니다.

문법

구문형태
함수function name(a, b) { ... }, export function name(input) { ... } (매개변수 최대 16개)
변수const name = value;, let name = value;, 재할당 name = value; (let만)
조건if (조건) { ... } else if (조건) { ... } else { ... }, 식 안에서는 조건 ? a : b
반복for (const item of items) { ... } (입력 최대 1,000개)
반환return value;
람다item => item.title, (sum, item) => sum + item.count (map·filter·reduce 인자로 사용)
값문자열, 숫자, true, false, null, 배열 [a, b], 객체 {key: value}
접근value.field, value["field"], value[0]

연산자는 우선순위가 낮은 것부터 ??, ||, &&, == != === !==, < > <= >=, + -, * / %이고, 단항 연산자는 !, -, +입니다.

배열 메서드는 items.map(fn), items.filter(fn), items.reduce(fn, initial) 세 가지입니다.

사용할 수 없는 것

while, class, new, this, async, await, delete, import, require, eval, Function, globalThis, process, __proto__, prototype, constructor는 예약어로 거부됩니다. 재귀 호출, 네트워크·파일·환경변수·난수·현재 시각 접근도 없습니다. 시각이 필요하면 화면 식에서 runtime.now·runtime.today를 계산해 인자로 넘깁니다.

내장 함수

이름동작
string.from(value)문자열로 변환. null은 "", 객체·배열은 JSON
string.trim(s), string.toLowerCase(s), string.toUpperCase(s)문자열 변환
string.includes(s, part)포함 여부
string.split(s, separator)나누기. separator가 ""이면 글자 단위
string.replaceAll(s, from, to)모두 바꾸기(from은 빈 문자열 불가, 결과 32 KiB 이하)
string.slice(s, start, end?)글자 단위 자르기
number.from(s)숫자 문자열을 숫자로
number.round(n), number.floor(n), number.ceil(n), number.abs(n)반올림·내림·올림·절댓값
number.min(a, b), number.max(a, b)최솟값·최댓값
array.join(items, separator?)문자열·숫자·boolean·null 배열을 이어 붙이기(기본 ,)
array.slice(items, start, end?)배열 자르기
array.includes(items, value)값 포함 여부(깊은 비교)
array.concat(a, b)배열 합치기(합계 1,000개 이하)
object.keys(value), object.values(value)정렬된 키·값 목록
object.has(value, key)키 존재 여부
date.iso(date)ISO 8601 시각 문자열
date.addDays(date, days)YYYY-MM-DD 날짜에 일수를 더한 날짜
date.weekday(date)요일(일요일 0 ~ 토요일 6)
html.toText(html)태그·script·style을 제거하고 entity를 풀어 텍스트로
html.lines(html)html.toText 결과를 비어 있지 않은 줄 목록으로
html.decodeEntities(text)HTML entity만 풀기

date.*는 YYYY-MM-DD 또는 시간대가 있는 ISO 시각만 받습니다. 타입이 맞지 않거나 목록에 없는 함수를 부르면 실행 오류(TYPE, DATE, FUNCTION)가 됩니다.

한도

항목한도
모듈패키지당 16개, 모듈당 32 KiB, 전체 소스 128 KiB
모듈 AST2,048 node, 호출 깊이 24, 중첩 32
화면 식 {{= ... }}UTF-8 256바이트, AST 64 node
실행 예산화면 식 10,000 step·2 MiB·16 ms, UI·computed 50,000 step·8 MiB·100 ms, 서버 transform 100,000 step·16 MiB·250 ms

컴파일된 manifest는 모듈 소스와 AST를 함께 담고 256 KiB 설치 한도를 넘을 수 없습니다. AST는 소스보다 훨씬 크므로(예제 기준 약 18배) 실제로 쓸 수 있는 소스 크기는 위 한도보다 작습니다. morit plugin validate가 한도 초과를 build 전에 알려 줍니다.

테스트

bash
npx -y @morit/cli plugin runtime-test . --module school --export normalizeDay \
  --fixture fixtures/day.json --now 2026-09-15T16:00:00Z --timezone Asia/Seoul --json

fixture 파일은 패키지에 포함되지 않습니다. 완성된 예제는 Runtime v3 예제를 참고하세요.