@moloodev/platform 0.5.0 → 0.7.0

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/package.json CHANGED
@@ -1,10 +1,9 @@
1
1
  {
2
2
  "name": "@moloodev/platform",
3
- "version": "0.5.0",
3
+ "version": "0.7.0",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": "./src/index.ts",
7
- "./builtin-editors": "./src/builtin-editors.ts",
8
7
  "./network": "./src/network.ts",
9
8
  "./dev-certs": "./src/dev-certs.ts",
10
9
  "./constants": "./src/constants.ts",
@@ -12,6 +11,7 @@
12
11
  "./occupancy-protocol": "./src/occupancy-protocol.ts",
13
12
  "./file-content": "./src/file-content.ts",
14
13
  "./bundle": "./src/bundle.ts",
14
+ "./editor-track": "./src/editor-track.ts",
15
15
  "./file-delivery": "./src/file-delivery.ts",
16
16
  "./ids": "./src/ids.ts"
17
17
  },
@@ -23,7 +23,7 @@
23
23
  "@types/node": "^24.13.3",
24
24
  "tsx": "^4.23.13",
25
25
  "typescript": "^7.0.2",
26
- "@moloodev/typescript-config": "0.5.0"
26
+ "@moloodev/typescript-config": "0.7.0"
27
27
  },
28
28
  "publishConfig": {
29
29
  "access": "public"
@@ -189,9 +189,7 @@ export function patternForContentType(contentType: string): KnownPatternId {
189
189
 
190
190
  const COMPOUND_SCHEMA_BY_SUFFIX: readonly [string, string][] = [
191
191
  [".layout.json", FIRST_PARTY_SCHEMAS.layout],
192
- [".mlayout", FIRST_PARTY_SCHEMAS.layout],
193
192
  [".catalog.json", FIRST_PARTY_SCHEMAS.catalog],
194
- [".mcat", FIRST_PARTY_SCHEMAS.catalog],
195
193
  [".table.json", FIRST_PARTY_SCHEMAS.table],
196
194
  [".loop.json", FIRST_PARTY_SCHEMAS.loop],
197
195
  [".bundle.json", FIRST_PARTY_SCHEMAS.bundle],
@@ -199,8 +197,6 @@ const COMPOUND_SCHEMA_BY_SUFFIX: readonly [string, string][] = [
199
197
 
200
198
  const EXTENSION_MIME_MAP: Record<string, { contentType: string; storageMode: StorageMode }> = {
201
199
  ".json": { contentType: "application/json", storageMode: "json" },
202
- ".mlayout": { contentType: "application/json", storageMode: "json" },
203
- ".mcat": { contentType: "application/json", storageMode: "json" },
204
200
  ".md": { contentType: "text/markdown", storageMode: "text" },
205
201
  ".markdown": { contentType: "text/markdown", storageMode: "text" },
206
202
  ".txt": { contentType: "text/plain", storageMode: "text" },
@@ -0,0 +1,8 @@
1
+ import { z } from "zod";
2
+
3
+ export const editorStatusResponseSchema = z.object({ data: z.array(z.object({
4
+ id: z.string(), revision: z.number().int(), status: z.string(),
5
+ tracks: z.array(z.enum(["stable", "beta"])),
6
+ submittedAt: z.string(), reviewedAt: z.string().nullable(), rejectionReason: z.string().nullable(),
7
+ checkFindings: z.array(z.object({ code: z.string(), detail: z.string() })),
8
+ })) });
@@ -0,0 +1,8 @@
1
+ /** Release tracks. A track points at one editor revision; `stable` is the default. */
2
+ export const EDITOR_TRACKS = ["stable", "beta"] as const;
3
+
4
+ export type EditorTrack = (typeof EDITOR_TRACKS)[number];
5
+
6
+ export function isEditorTrack(value: unknown): value is EditorTrack {
7
+ return typeof value === "string" && (EDITOR_TRACKS as readonly string[]).includes(value);
8
+ }
package/src/index.ts CHANGED
@@ -88,5 +88,9 @@ export * from "./bundle";
88
88
  export * from "./file-delivery";
89
89
 
90
90
  export { loopbackOrigin } from "./editor-dev";
91
+ export { editorStatusResponseSchema } from "./editor-status";
92
+ export { EDITOR_TRACKS, isEditorTrack, type EditorTrack } from "./editor-track";
91
93
 
92
94
  export type { PublishTarget } from "./publish-target";
95
+ export { PUBLISH_ERROR_MESSAGES, publishErrorBody, parsePublishName } from "./publish-target";
96
+ export { isPublisherHandle, isReservedPublisherHandle, reservedPublishers } from "./publisher-handle";
@@ -1,3 +1,34 @@
1
- export type PublishTarget =
2
- | { kind: "workspace"; workspaceSlug: string }
3
- | { kind: "builtin" };
1
+ import { isPublisherHandle } from "./publisher-handle";
2
+ import { parseQualifiedName } from "./qualified-name";
3
+
4
+ export type PublishTarget = { kind: "workspace"; workspaceSlug: string };
5
+
6
+ export function parsePublishName(id: string) {
7
+ const dot = id.indexOf(".");
8
+ if (dot !== -1 && !isPublisherHandle(id.slice(0, dot))) {
9
+ return { ok: false, error: "invalid_publisher_handle" } as const;
10
+ }
11
+ const name = parseQualifiedName(id);
12
+ return name ? { ok: true, name } as const : { ok: false, error: "invalid_manifest" } as const;
13
+ }
14
+
15
+ /** Shared copy for API responses and CLI fallbacks. Services return only codes. */
16
+ export const PUBLISH_ERROR_MESSAGES = {
17
+ invalid_publisher_handle: "Publisher handles must be 2–39 lowercase letters, digits or hyphens, start with a letter, and have no trailing or consecutive hyphens.",
18
+ publisher_reserved: "This publisher handle is reserved. Choose another handle.",
19
+ publisher_taken: "This publisher is managed by another workspace. Select its managing workspace or choose another handle.",
20
+ publisher_suspended: "This publisher is suspended. Contact moloo support.",
21
+ forbidden: "You must be an owner or admin of the publisher's managing workspace.",
22
+ invalid_manifest: "The editor manifest is invalid.",
23
+ unknown_workspace: "The selected workspace does not exist.",
24
+ unknown_editor: "No submitted editor with this manifest id exists in the selected workspace.",
25
+ checks_failed: "Editor checks failed. Fix the findings before publishing again.",
26
+ behind_stable: "This revision is older than the stable revision. Publish a new build to beta.",
27
+ no_beta: "This editor has no beta revision to promote.",
28
+ } as const;
29
+
30
+ export function publishErrorBody(error: string): { error: string; message?: string } {
31
+ const message = Object.hasOwn(PUBLISH_ERROR_MESSAGES, error)
32
+ ? PUBLISH_ERROR_MESSAGES[error as keyof typeof PUBLISH_ERROR_MESSAGES] : undefined;
33
+ return { error, ...(message ? { message } : {}) };
34
+ }
@@ -0,0 +1,18 @@
1
+ const HANDLE = /^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/;
2
+
3
+ export const reservedPublishers: readonly string[] = [
4
+ "moloo", "admin", "administrator", "official", "system", "support", "api", "app",
5
+ "www", "root", "staff", "team", "help", "security", "null", "undefined",
6
+ "auth", "id", "login", "oauth", "account", "accounts", "billing", "status",
7
+ "internal", "platform", "moderator", "abuse", "postmaster", "webmaster",
8
+ "static", "cdn", "preview", "dev", "localhost", "local", "mail",
9
+ ];
10
+ const RESERVED = new Set(reservedPublishers);
11
+
12
+ export function isPublisherHandle(handle: string): boolean {
13
+ return handle.length >= 2 && handle.length <= 39 && HANDLE.exec(handle)?.[0] === handle;
14
+ }
15
+
16
+ export function isReservedPublisherHandle(handle: string): boolean {
17
+ return RESERVED.has(handle);
18
+ }
@@ -3,7 +3,9 @@
3
3
  * Shared by editor ids and asset kind ids.
4
4
  * @see https://code.visualstudio.com/api/references/extension-manifest
5
5
  */
6
- const QUALIFIED_NAME = /^([a-z0-9A-Z][a-z0-9-A-Z]*)\.([a-z0-9A-Z][a-z0-9-A-Z]*)$/;
6
+ import { isPublisherHandle } from "./publisher-handle";
7
+
8
+ const QUALIFIED_NAME = /^([^.]+)\.([a-z0-9A-Z][a-z0-9-A-Z]*)$/;
7
9
 
8
10
  export type QualifiedName = {
9
11
  publisher: string;
@@ -12,10 +14,10 @@ export type QualifiedName = {
12
14
 
13
15
  export function parseQualifiedName(id: string): QualifiedName | null {
14
16
  const match = QUALIFIED_NAME.exec(id);
15
- if (!match) return null;
17
+ if (!match || !isPublisherHandle(match[1]!)) return null;
16
18
  return { publisher: match[1]!, name: match[2]! };
17
19
  }
18
20
 
19
21
  export function isQualifiedName(id: string): boolean {
20
- return QUALIFIED_NAME.test(id);
22
+ return parseQualifiedName(id) !== null;
21
23
  }
@@ -1,15 +0,0 @@
1
- export const builtinEditors = [
2
- { id: "091d9isv5yp3x5mhwum08p1f", publisherHandle: "moloo", slug: "markdown" },
3
- { id: "1o5gtual80gchlsd5uug3wfv", publisherHandle: "moloo", slug: "loop" },
4
- { id: "g6qihgfq096rsp3k1kimttvy", publisherHandle: "moloo", slug: "table" },
5
- { id: "2cnatugu7hupo4stgh2srv68", publisherHandle: "moloo", slug: "bundle" },
6
- { id: "uqq597gzhpzkds0mrmc2zdtu", publisherHandle: "moloo", slug: "layout" },
7
- ] as const;
8
-
9
- export function builtinEditorId(
10
- slug: (typeof builtinEditors)[number]["slug"],
11
- ): string {
12
- const row = builtinEditors.find((item) => item.slug === slug);
13
- if (row === undefined) throw new Error(`builtin editor ${slug} is missing`);
14
- return row.id;
15
- }