@selvajs/platform 0.15.0-beta.4 → 0.15.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.
Files changed (48) hide show
  1. package/dist/definitions/schemas.d.ts +1 -1
  2. package/dist/organizations/schemas.d.ts +2 -2
  3. package/dist/shareLinks/schemas.d.ts +1 -1
  4. package/dist/storage/image.js.map +1 -1
  5. package/dist/testing/suites/storageProviderSuite.d.ts.map +1 -1
  6. package/dist/testing/suites/storageProviderSuite.js +9 -4
  7. package/dist/testing/suites/storageProviderSuite.js.map +1 -1
  8. package/package.json +4 -4
  9. package/dist/auth.d.ts +0 -59
  10. package/dist/auth.d.ts.map +0 -1
  11. package/dist/auth.js +0 -12
  12. package/dist/auth.js.map +0 -1
  13. package/dist/compute.d.ts +0 -47
  14. package/dist/compute.d.ts.map +0 -1
  15. package/dist/compute.js +0 -11
  16. package/dist/compute.js.map +0 -1
  17. package/dist/definitions/service.d.ts +0 -63
  18. package/dist/definitions/service.d.ts.map +0 -1
  19. package/dist/definitions/service.js +0 -162
  20. package/dist/definitions/service.js.map +0 -1
  21. package/dist/definitions.d.ts +0 -135
  22. package/dist/definitions.d.ts.map +0 -1
  23. package/dist/definitions.js +0 -23
  24. package/dist/definitions.js.map +0 -1
  25. package/dist/invites/schemas.d.ts +0 -24
  26. package/dist/invites/schemas.d.ts.map +0 -1
  27. package/dist/invites/schemas.js +0 -17
  28. package/dist/invites/schemas.js.map +0 -1
  29. package/dist/organizations.d.ts +0 -93
  30. package/dist/organizations.d.ts.map +0 -1
  31. package/dist/organizations.js +0 -14
  32. package/dist/organizations.js.map +0 -1
  33. package/dist/testing/adapterSuite.d.ts +0 -33
  34. package/dist/testing/adapterSuite.d.ts.map +0 -1
  35. package/dist/testing/adapterSuite.js +0 -166
  36. package/dist/testing/adapterSuite.js.map +0 -1
  37. package/dist/testing/orgStoreSuite.d.ts +0 -32
  38. package/dist/testing/orgStoreSuite.d.ts.map +0 -1
  39. package/dist/testing/orgStoreSuite.js +0 -363
  40. package/dist/testing/orgStoreSuite.js.map +0 -1
  41. package/dist/testing/storageProviderSuite.d.ts +0 -30
  42. package/dist/testing/storageProviderSuite.d.ts.map +0 -1
  43. package/dist/testing/storageProviderSuite.js +0 -122
  44. package/dist/testing/storageProviderSuite.js.map +0 -1
  45. package/dist/testing/suites/runner.d.ts +0 -21
  46. package/dist/testing/suites/runner.d.ts.map +0 -1
  47. package/dist/testing/suites/runner.js +0 -7
  48. package/dist/testing/suites/runner.js.map +0 -1
@@ -1,135 +0,0 @@
1
- /**
2
- * Definition provider interfaces — independently swappable.
3
- *
4
- * File storage and metadata storage are deliberately split so you can mix:
5
- * - Filesystem files + Supabase DB metadata
6
- * - S3 files + local JSON metadata
7
- * - Everything through one backend (e.g. full Supabase)
8
- */
9
- export type DefinitionFileExt = 'gh' | 'ghx';
10
- /** File extensions accepted for Grasshopper definitions (with dot) */
11
- export declare const GH_EXTENSIONS: string[];
12
- /** Image extensions accepted for cover images (with dot) */
13
- export declare const COVER_IMAGE_EXTENSIONS: string[];
14
- /** All accepted upload extensions */
15
- export declare const ALLOWED_UPLOAD_EXTENSIONS: string[];
16
- /** MIME types for image extensions */
17
- export declare const COVER_IMAGE_CONTENT_TYPES: Record<string, string>;
18
- export interface DefinitionMeta {
19
- displayName: string;
20
- description?: string;
21
- category?: string;
22
- tags?: string[];
23
- /** Path or URL to cover image, provider-dependent */
24
- coverImage?: string;
25
- /** Original uploaded filename, kept for display only */
26
- originalFilename?: string;
27
- }
28
- /**
29
- * A single entry in the file version history.
30
- * Stored by the meta provider; the actual bytes are stored by the file provider.
31
- */
32
- export interface HistoryEntry {
33
- /**
34
- * Provider-specific reference to the archived file.
35
- * Filesystem: timestamped filename (e.g. "2024-01-15T10-30-45-123Z_definition.gh").
36
- * S3 / Supabase: object key or storage path.
37
- */
38
- ref: string;
39
- /** Original uploaded filename, for display purposes */
40
- originalName: string;
41
- /** ISO 8601 date of when the file was archived */
42
- archivedAt: string;
43
- }
44
- export interface DefinitionRecord {
45
- /** UUID v4 primary key */
46
- guid: string;
47
- /** UUID of the project that owns this definition */
48
- projectId: string;
49
- /** UUID of the user who created this definition */
50
- ownerId: string;
51
- /**
52
- * Optional UUID of a specific compute server to use when solving.
53
- * Falls back to the org default, then the platform default.
54
- */
55
- computeServerId?: string;
56
- fileExt: DefinitionFileExt;
57
- meta: DefinitionMeta;
58
- /** File version history, newest first */
59
- history: HistoryEntry[];
60
- /** Maximum archived versions to keep. 0 = unlimited. */
61
- maxHistory: number;
62
- createdAt: string;
63
- updatedAt: string;
64
- }
65
- /**
66
- * File storage provider: where .gh / .ghx binaries, archived versions, and preview images live.
67
- *
68
- * Implement with: local filesystem, S3, Supabase Storage, Azure Blob, etc.
69
- */
70
- export interface IDefinitionFileProvider {
71
- /** Load the active Grasshopper definition binary. Returns null if not found. */
72
- getFile(guid: string): Promise<Uint8Array | null>;
73
- /** Load the preview image bytes. Returns null if no image exists. */
74
- getPreviewImage(guid: string): Promise<Uint8Array | null>;
75
- /**
76
- * Load an archived file by its provider-specific ref.
77
- * Used when reverting to a previous version.
78
- */
79
- getArchivedFile(guid: string, ref: string): Promise<Uint8Array | null>;
80
- /** Store the active definition file. Overwrites any existing active file. */
81
- saveFile(guid: string, data: Uint8Array, ext: DefinitionFileExt): Promise<void>;
82
- /**
83
- * Archive the current active file before replacing it.
84
- * Returns a HistoryEntry (with provider-specific ref) to be saved by the meta provider.
85
- * Returns null if there is no current active file to archive.
86
- */
87
- archiveCurrentFile(guid: string, originalName: string): Promise<HistoryEntry | null>;
88
- /**
89
- * Delete a specific archived version by its ref.
90
- * Called when pruning history that exceeds maxHistory.
91
- */
92
- deleteArchivedFile(guid: string, ref: string): Promise<void>;
93
- /** Store a preview image (expected to be WebP). */
94
- saveImage(guid: string, data: Uint8Array): Promise<void>;
95
- /**
96
- * Returns the public URL for the stored cover image after a saveImage() call.
97
- * Called immediately after saveImage() so the URL can be persisted in metadata.
98
- * Filesystem: returns "/api/definitions/{guid}/image/cover.webp".
99
- * S3/Supabase: returns the CDN or signed URL for the uploaded image.
100
- */
101
- getCoverImageUrl(guid: string): string;
102
- /** Delete all files associated with a GUID (active file, archives, image). */
103
- deleteFiles(guid: string): Promise<void>;
104
- }
105
- /**
106
- * Metadata storage provider: where definition config, metadata, and file history live.
107
- *
108
- * Implement with: local JSON file, Supabase DB, DynamoDB, PostgreSQL, etc.
109
- */
110
- export interface IDefinitionMetaProvider {
111
- /** List all definition records, sorted by displayName. */
112
- list(): Promise<DefinitionRecord[]>;
113
- /** List all definitions belonging to a specific project. */
114
- listByProject(projectId: string): Promise<DefinitionRecord[]>;
115
- /** List definitions that belong to projects with public visibility. */
116
- listPublic(): Promise<DefinitionRecord[]>;
117
- /** Get a single record by GUID. Returns null if not found. */
118
- get(guid: string): Promise<DefinitionRecord | null>;
119
- /** Create a new definition record. */
120
- create(record: DefinitionRecord): Promise<void>;
121
- /** Merge a partial metadata update into an existing record. */
122
- update(guid: string, patch: Partial<DefinitionMeta>): Promise<void>;
123
- /**
124
- * Prepend a new history entry and optionally prune old entries.
125
- * The file provider has already archived the bytes; this just updates the metadata.
126
- */
127
- addHistoryEntry(guid: string, entry: HistoryEntry): Promise<void>;
128
- /**
129
- * Remove a history entry by ref (after the file provider has deleted the bytes).
130
- */
131
- removeHistoryEntry(guid: string, ref: string): Promise<void>;
132
- /** Delete a definition record entirely. */
133
- delete(guid: string): Promise<void>;
134
- }
135
- //# sourceMappingURL=definitions.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"definitions.d.ts","sourceRoot":"","sources":["../src/definitions.ts"],"names":[],"mappings":"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"}
@@ -1,23 +0,0 @@
1
- /**
2
- * Definition provider interfaces — independently swappable.
3
- *
4
- * File storage and metadata storage are deliberately split so you can mix:
5
- * - Filesystem files + Supabase DB metadata
6
- * - S3 files + local JSON metadata
7
- * - Everything through one backend (e.g. full Supabase)
8
- */
9
- /** File extensions accepted for Grasshopper definitions (with dot) */
10
- export const GH_EXTENSIONS = ['.gh', '.ghx'];
11
- /** Image extensions accepted for cover images (with dot) */
12
- export const COVER_IMAGE_EXTENSIONS = ['.jpg', '.jpeg', '.png', '.webp', '.gif'];
13
- /** All accepted upload extensions */
14
- export const ALLOWED_UPLOAD_EXTENSIONS = [...GH_EXTENSIONS, ...COVER_IMAGE_EXTENSIONS];
15
- /** MIME types for image extensions */
16
- export const COVER_IMAGE_CONTENT_TYPES = {
17
- '.jpg': 'image/jpeg',
18
- '.jpeg': 'image/jpeg',
19
- '.png': 'image/png',
20
- '.webp': 'image/webp',
21
- '.gif': 'image/gif'
22
- };
23
- //# sourceMappingURL=definitions.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"definitions.js","sourceRoot":"","sources":["../src/definitions.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,sEAAsE;AACtE,MAAM,CAAC,MAAM,aAAa,GAAa,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;AAEvD,4DAA4D;AAC5D,MAAM,CAAC,MAAM,sBAAsB,GAAa,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;AAE3F,qCAAqC;AACrC,MAAM,CAAC,MAAM,yBAAyB,GAAa,CAAC,GAAG,aAAa,EAAE,GAAG,sBAAsB,CAAC,CAAC;AAEjG,sCAAsC;AACtC,MAAM,CAAC,MAAM,yBAAyB,GAA2B;IAChE,MAAM,EAAE,YAAY;IACpB,OAAO,EAAE,YAAY;IACrB,MAAM,EAAE,WAAW;IACnB,OAAO,EAAE,YAAY;IACrB,MAAM,EAAE,WAAW;CACnB,CAAC"}
@@ -1,24 +0,0 @@
1
- import { z } from 'zod';
2
- export declare const CreateInviteInputSchema: z.ZodObject<{
3
- email: z.ZodPipe<z.ZodString, z.ZodTransform<string, string>>;
4
- orgId: z.ZodString;
5
- orgRole: z.ZodEnum<{
6
- owner: "owner";
7
- admin: "admin";
8
- member: "member";
9
- }>;
10
- orgPermissions: z.ZodDefault<z.ZodArray<z.ZodEnum<{
11
- manage_users: "manage_users";
12
- manage_compute: "manage_compute";
13
- manage_definitions: "manage_definitions";
14
- manage_projects: "manage_projects";
15
- }>>>;
16
- }, z.core.$strip>;
17
- export declare const AcceptInviteInputSchema: z.ZodObject<{
18
- token: z.ZodString;
19
- password: z.ZodString;
20
- displayName: z.ZodOptional<z.ZodString>;
21
- }, z.core.$strip>;
22
- export type CreateInviteInput = z.infer<typeof CreateInviteInputSchema>;
23
- export type AcceptInviteInput = z.infer<typeof AcceptInviteInputSchema>;
24
- //# sourceMappingURL=schemas.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"schemas.d.ts","sourceRoot":"","sources":["../../src/invites/schemas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;iBAQlC,CAAC;AAEH,eAAO,MAAM,uBAAuB;;;;iBAIlC,CAAC;AAEH,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AACxE,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC"}
@@ -1,17 +0,0 @@
1
- import { z } from 'zod';
2
- import { OrgRoleSchema, OrgPermissionSchema } from '../organizations/schemas.js';
3
- export const CreateInviteInputSchema = z.object({
4
- email: z
5
- .string()
6
- .email('Valid email is required')
7
- .transform((s) => s.toLowerCase()),
8
- orgId: z.string().uuid(),
9
- orgRole: OrgRoleSchema,
10
- orgPermissions: z.array(OrgPermissionSchema).default([])
11
- });
12
- export const AcceptInviteInputSchema = z.object({
13
- token: z.string().min(20),
14
- password: z.string().min(8, 'Password must be at least 8 characters'),
15
- displayName: z.string().trim().max(128).optional()
16
- });
17
- //# sourceMappingURL=schemas.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"schemas.js","sourceRoot":"","sources":["../../src/invites/schemas.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAEjF,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC/C,KAAK,EAAE,CAAC;SACN,MAAM,EAAE;SACR,KAAK,CAAC,yBAAyB,CAAC;SAChC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;IACnC,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE;IACxB,OAAO,EAAE,aAAa;IACtB,cAAc,EAAE,CAAC,CAAC,KAAK,CAAC,mBAAmB,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;CACxD,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC/C,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC;IACzB,QAAQ,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,EAAE,wCAAwC,CAAC;IACrE,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE;CAClD,CAAC,CAAC"}
@@ -1,93 +0,0 @@
1
- /**
2
- * Organization and Project provider interfaces.
3
- *
4
- * Models a three-level ownership hierarchy:
5
- * Platform → Organization → Project → Definition
6
- *
7
- * Implement for any backend:
8
- * - Local JSON files (built-in default)
9
- * - Supabase (row-level security tables)
10
- * - Firebase Firestore
11
- * - Any relational database
12
- */
13
- export interface Organization {
14
- /** UUID v4 primary key */
15
- id: string;
16
- /** Human-readable display name */
17
- name: string;
18
- /** URL-safe unique identifier, e.g. "acme-corp" */
19
- slug: string;
20
- /** UUID of the user who owns this org */
21
- ownerId: string;
22
- createdAt: string;
23
- updatedAt: string;
24
- }
25
- export type OrgRole = 'owner' | 'admin' | 'member';
26
- export interface OrgMember {
27
- orgId: string;
28
- userId: string;
29
- role: OrgRole;
30
- joinedAt: string;
31
- }
32
- /**
33
- * Who can invoke solve on definitions in this project:
34
- * - 'public' — any authenticated user
35
- * - 'org' — any member of the parent organization
36
- * - 'private' — only users listed in ProjectMember
37
- */
38
- export type ProjectVisibility = 'public' | 'org' | 'private';
39
- export type ProjectRole = 'owner' | 'editor' | 'viewer';
40
- export interface Project {
41
- /** UUID v4 primary key */
42
- id: string;
43
- /** UUID of the owning organization */
44
- orgId: string;
45
- name: string;
46
- /** URL-safe, unique within the organization */
47
- slug: string;
48
- description?: string;
49
- visibility: ProjectVisibility;
50
- /** UUID of the user who created this project */
51
- ownerId: string;
52
- createdAt: string;
53
- updatedAt: string;
54
- }
55
- export interface ProjectMember {
56
- projectId: string;
57
- userId: string;
58
- role: ProjectRole;
59
- joinedAt: string;
60
- }
61
- export interface IOrganizationProvider {
62
- listOrgs(): Promise<Organization[]>;
63
- getOrg(id: string): Promise<Organization | null>;
64
- getOrgBySlug(slug: string): Promise<Organization | null>;
65
- createOrg(org: Organization): Promise<void>;
66
- /** Patch mutable org fields. Only name and slug may be changed after creation. */
67
- updateOrg(id: string, patch: Partial<Pick<Organization, 'name' | 'slug'>>): Promise<void>;
68
- /** Delete an org and all its projects (cascade is implementation-specific). */
69
- deleteOrg(id: string): Promise<void>;
70
- listOrgMembers(orgId: string): Promise<OrgMember[]>;
71
- getOrgMember(orgId: string, userId: string): Promise<OrgMember | null>;
72
- addOrgMember(member: OrgMember): Promise<void>;
73
- updateOrgMemberRole(orgId: string, userId: string, role: OrgRole): Promise<void>;
74
- removeOrgMember(orgId: string, userId: string): Promise<void>;
75
- listProjects(orgId: string): Promise<Project[]>;
76
- getProject(id: string): Promise<Project | null>;
77
- getProjectBySlug(orgId: string, slug: string): Promise<Project | null>;
78
- createProject(project: Project): Promise<void>;
79
- updateProject(id: string, patch: Partial<Pick<Project, 'name' | 'slug' | 'description' | 'visibility'>>): Promise<void>;
80
- deleteProject(id: string): Promise<void>;
81
- listProjectMembers(projectId: string): Promise<ProjectMember[]>;
82
- getProjectMember(projectId: string, userId: string): Promise<ProjectMember | null>;
83
- addProjectMember(member: ProjectMember): Promise<void>;
84
- updateProjectMemberRole(projectId: string, userId: string, role: ProjectRole): Promise<void>;
85
- removeProjectMember(projectId: string, userId: string): Promise<void>;
86
- /** Returns true if the user may invoke solve on any definition in the project. */
87
- canSolve(userId: string, projectId: string): Promise<boolean>;
88
- /** Returns true if the user may upload or modify definitions in the project. */
89
- canEdit(userId: string, projectId: string): Promise<boolean>;
90
- /** Returns true if the user may manage project members and settings. */
91
- canManage(userId: string, projectId: string): Promise<boolean>;
92
- }
93
- //# sourceMappingURL=organizations.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"organizations.d.ts","sourceRoot":"","sources":["../src/organizations.ts"],"names":[],"mappings":"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"}
@@ -1,14 +0,0 @@
1
- /**
2
- * Organization and Project provider interfaces.
3
- *
4
- * Models a three-level ownership hierarchy:
5
- * Platform → Organization → Project → Definition
6
- *
7
- * Implement for any backend:
8
- * - Local JSON files (built-in default)
9
- * - Supabase (row-level security tables)
10
- * - Firebase Firestore
11
- * - Any relational database
12
- */
13
- export {};
14
- //# sourceMappingURL=organizations.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"organizations.js","sourceRoot":"","sources":["../src/organizations.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG"}
@@ -1,33 +0,0 @@
1
- /**
2
- * Adapter conformance suite for IDefinitionStore.
3
- *
4
- * The goal is to prove every adapter behaves identically from the consuming
5
- * app's perspective — `ctx` scoping, `pending` filtering, `listStalePending`
6
- * cutoff, history mutations, and error shapes.
7
- *
8
- * Runner-agnostic: callers inject a `{ describe, it, expect }` trio so this
9
- * package stays test-framework free. For vitest or jest, pass the globals
10
- * directly; for node:test, wrap them.
11
- */
12
- import type { IDefinitionStore } from '../data/interface.js';
13
- export interface ConformanceRunner {
14
- describe: (name: string, fn: () => void) => void;
15
- it: (name: string, fn: () => Promise<void> | void) => void;
16
- expect: <T>(actual: T) => {
17
- toBe: (expected: T) => void;
18
- toEqual: (expected: unknown) => void;
19
- toBeNull: () => void;
20
- toBeTruthy: () => void;
21
- toContain: (expected: unknown) => void;
22
- };
23
- }
24
- export interface DefinitionStoreConformanceOptions {
25
- /** Name to show in the test output (e.g. "local-provider"). */
26
- name: string;
27
- /** Factory that returns a fresh, empty store per test. */
28
- createStore: () => Promise<IDefinitionStore> | IDefinitionStore;
29
- /** Test runner globals injected from the host package. */
30
- runner: ConformanceRunner;
31
- }
32
- export declare function runDefinitionStoreConformance(opts: DefinitionStoreConformanceOptions): void;
33
- //# sourceMappingURL=adapterSuite.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"adapterSuite.d.ts","sourceRoot":"","sources":["../../src/testing/adapterSuite.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAM7D,MAAM,WAAW,iBAAiB;IACjC,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,IAAI,KAAK,IAAI,CAAC;IACjD,EAAE,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,KAAK,IAAI,CAAC;IAC3D,MAAM,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,KAAK;QACzB,IAAI,EAAE,CAAC,QAAQ,EAAE,CAAC,KAAK,IAAI,CAAC;QAC5B,OAAO,EAAE,CAAC,QAAQ,EAAE,OAAO,KAAK,IAAI,CAAC;QACrC,QAAQ,EAAE,MAAM,IAAI,CAAC;QACrB,UAAU,EAAE,MAAM,IAAI,CAAC;QACvB,SAAS,EAAE,CAAC,QAAQ,EAAE,OAAO,KAAK,IAAI,CAAC;KACvC,CAAC;CACF;AAED,MAAM,WAAW,iCAAiC;IACjD,+DAA+D;IAC/D,IAAI,EAAE,MAAM,CAAC;IACb,0DAA0D;IAC1D,WAAW,EAAE,MAAM,OAAO,CAAC,gBAAgB,CAAC,GAAG,gBAAgB,CAAC;IAChE,0DAA0D;IAC1D,MAAM,EAAE,iBAAiB,CAAC;CAC1B;AA4BD,wBAAgB,6BAA6B,CAAC,IAAI,EAAE,iCAAiC,GAAG,IAAI,CA0J3F"}
@@ -1,166 +0,0 @@
1
- /**
2
- * Adapter conformance suite for IDefinitionStore.
3
- *
4
- * The goal is to prove every adapter behaves identically from the consuming
5
- * app's perspective — `ctx` scoping, `pending` filtering, `listStalePending`
6
- * cutoff, history mutations, and error shapes.
7
- *
8
- * Runner-agnostic: callers inject a `{ describe, it, expect }` trio so this
9
- * package stays test-framework free. For vitest or jest, pass the globals
10
- * directly; for node:test, wrap them.
11
- */
12
- import { SYSTEM_CONTEXT } from '../context.js';
13
- function ctx(userId, permissions = ['platform_admin']) {
14
- return { userId, permissions };
15
- }
16
- function record(overrides = {}) {
17
- const now = new Date().toISOString();
18
- return {
19
- guid: overrides.guid ?? cryptoRandom(),
20
- projectId: overrides.projectId ?? 'project-1',
21
- ownerId: overrides.ownerId ?? 'user-1',
22
- fileExt: overrides.fileExt ?? 'gh',
23
- meta: overrides.meta ?? { displayName: 'Test' },
24
- history: overrides.history ?? [],
25
- maxHistory: overrides.maxHistory ?? 10,
26
- status: overrides.status ?? 'ready',
27
- createdAt: overrides.createdAt ?? now,
28
- updatedAt: overrides.updatedAt ?? now,
29
- ...overrides
30
- };
31
- }
32
- // Minimal UUID-ish helper — good enough for tests, no crypto import needed.
33
- function cryptoRandom() {
34
- return `test-${Math.random().toString(36).slice(2, 10)}`;
35
- }
36
- export function runDefinitionStoreConformance(opts) {
37
- const { name, createStore, runner } = opts;
38
- const { describe, it, expect } = runner;
39
- describe(`IDefinitionStore conformance: ${name}`, () => {
40
- it('create + get returns the record', async () => {
41
- const store = await createStore();
42
- const rec = record({ guid: 'g1' });
43
- await store.create(ctx('u1'), rec);
44
- const got = await store.get(ctx('u1'), 'g1');
45
- expect(got?.guid).toBe('g1');
46
- });
47
- it('get returns null for missing guid', async () => {
48
- const store = await createStore();
49
- const got = await store.get(ctx('u1'), 'does-not-exist');
50
- expect(got).toBeNull();
51
- });
52
- it('list filters pending by default', async () => {
53
- const store = await createStore();
54
- await store.create(ctx('u1'), record({ guid: 'r1', status: 'ready' }));
55
- await store.create(ctx('u1'), record({ guid: 'p1', status: 'pending' }));
56
- const page = await store.list(ctx('u1'));
57
- const guids = page.items.map((r) => r.guid);
58
- expect(guids).toContain('r1');
59
- expect(guids.includes('p1')).toBe(false);
60
- });
61
- it('list with includePending returns pending too', async () => {
62
- const store = await createStore();
63
- await store.create(ctx('u1'), record({ guid: 'r1', status: 'ready' }));
64
- await store.create(ctx('u1'), record({ guid: 'p1', status: 'pending' }));
65
- const page = await store.list(ctx('u1'), { includePending: true });
66
- const guids = page.items.map((r) => r.guid);
67
- expect(guids).toContain('r1');
68
- expect(guids).toContain('p1');
69
- });
70
- it('listByProject filters by projectId', async () => {
71
- const store = await createStore();
72
- await store.create(ctx('u1'), record({ guid: 'a', projectId: 'proj-a' }));
73
- await store.create(ctx('u1'), record({ guid: 'b', projectId: 'proj-b' }));
74
- const page = await store.listByProject(ctx('u1'), 'proj-a');
75
- const guids = page.items.map((r) => r.guid);
76
- expect(guids).toEqual(['a']);
77
- });
78
- it('update applies patch and bumps updatedAt', async () => {
79
- const store = await createStore();
80
- const created = record({ guid: 'u1', meta: { displayName: 'Old' } });
81
- await store.create(ctx('u1'), created);
82
- await store.update(ctx('u1'), 'u1', { meta: { displayName: 'New' } });
83
- const got = await store.get(ctx('u1'), 'u1');
84
- expect(got?.meta.displayName).toBe('New');
85
- expect(got.updatedAt >= created.updatedAt).toBe(true);
86
- });
87
- it('update on missing guid throws ProviderError with status 404', async () => {
88
- const store = await createStore();
89
- let thrown;
90
- try {
91
- await store.update(ctx('u1'), 'nope', { meta: { displayName: 'X' } });
92
- }
93
- catch (err) {
94
- thrown = err;
95
- }
96
- expect(thrown).toBeTruthy();
97
- const e = thrown;
98
- expect(e.statusCode).toBe(404);
99
- });
100
- it('status flip pending → ready via update', async () => {
101
- const store = await createStore();
102
- await store.create(ctx('u1'), record({ guid: 'x', status: 'pending' }));
103
- const beforeFlip = await store.list(ctx('u1'));
104
- expect(beforeFlip.items.map((r) => r.guid).includes('x')).toBe(false);
105
- await store.update(ctx('u1'), 'x', { status: 'ready' });
106
- const afterFlip = await store.list(ctx('u1'));
107
- expect(afterFlip.items.map((r) => r.guid)).toContain('x');
108
- });
109
- it('addHistoryEntry prepends entries (newest first)', async () => {
110
- const store = await createStore();
111
- await store.create(ctx('u1'), record({ guid: 'h', maxHistory: 0 }));
112
- const e1 = { ref: 'r1', originalName: 'a.gh', archivedAt: '2024-01-01' };
113
- const e2 = { ref: 'r2', originalName: 'b.gh', archivedAt: '2024-01-02' };
114
- await store.addHistoryEntry(ctx('u1'), 'h', e1);
115
- await store.addHistoryEntry(ctx('u1'), 'h', e2);
116
- const got = await store.get(ctx('u1'), 'h');
117
- expect(got.history.map((h) => h.ref)).toEqual(['r2', 'r1']);
118
- });
119
- it('removeHistoryEntry removes the matching ref', async () => {
120
- const store = await createStore();
121
- const entry = { ref: 'keep', originalName: 'a.gh', archivedAt: '2024-01-01' };
122
- const drop = { ref: 'drop', originalName: 'b.gh', archivedAt: '2024-01-02' };
123
- await store.create(ctx('u1'), record({ guid: 'h', history: [drop, entry] }));
124
- await store.removeHistoryEntry(ctx('u1'), 'h', 'drop');
125
- const got = await store.get(ctx('u1'), 'h');
126
- expect(got.history.map((h) => h.ref)).toEqual(['keep']);
127
- });
128
- it('delete removes the record', async () => {
129
- const store = await createStore();
130
- await store.create(ctx('u1'), record({ guid: 'd' }));
131
- await store.delete(ctx('u1'), 'd');
132
- const got = await store.get(ctx('u1'), 'd');
133
- expect(got).toBeNull();
134
- });
135
- it('listStalePending returns only pending + older than cutoff', async () => {
136
- const store = await createStore();
137
- const old = '2024-01-01T00:00:00.000Z';
138
- const recent = new Date().toISOString();
139
- await store.create(ctx('u1'), record({ guid: 'old-pending', status: 'pending', createdAt: old }));
140
- await store.create(ctx('u1'), record({ guid: 'new-pending', status: 'pending', createdAt: recent }));
141
- await store.create(ctx('u1'), record({ guid: 'old-ready', status: 'ready', createdAt: old }));
142
- const cutoff = '2024-06-01T00:00:00.000Z';
143
- const stale = await store.listStalePending(SYSTEM_CONTEXT, cutoff);
144
- const guids = stale.map((r) => r.guid);
145
- expect(guids).toContain('old-pending');
146
- expect(guids.includes('new-pending')).toBe(false);
147
- expect(guids.includes('old-ready')).toBe(false);
148
- });
149
- it('pagination respects limit and nextCursor', async () => {
150
- const store = await createStore();
151
- for (let i = 0; i < 5; i++) {
152
- await store.create(ctx('u1'), record({ guid: `p${i}`, meta: { displayName: `N${i}` } }));
153
- }
154
- const first = await store.list(ctx('u1'), { limit: 2 });
155
- expect(first.items.length).toBe(2);
156
- expect(first.nextCursor).toBeTruthy();
157
- const second = await store.list(ctx('u1'), { limit: 2, cursor: first.nextCursor });
158
- expect(second.items.length).toBe(2);
159
- const firstGuids = new Set(first.items.map((r) => r.guid));
160
- for (const item of second.items) {
161
- expect(firstGuids.has(item.guid)).toBe(false);
162
- }
163
- });
164
- });
165
- }
166
- //# sourceMappingURL=adapterSuite.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"adapterSuite.js","sourceRoot":"","sources":["../../src/testing/adapterSuite.ts"],"names":[],"mappings":"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"}
@@ -1,32 +0,0 @@
1
- /**
2
- * Adapter conformance suite for IOrgStore.
3
- *
4
- * Tests organization and project CRUD, membership management, pagination,
5
- * and error handling to ensure all adapters behave identically.
6
- *
7
- * Runner-agnostic: callers inject a `{ describe, it, expect }` trio.
8
- */
9
- import type { IOrgStore } from '../data/interface.js';
10
- export interface ConformanceRunner {
11
- describe: (name: string, fn: () => void) => void;
12
- it: (name: string, fn: () => Promise<void> | void) => void;
13
- expect: <T>(actual: T) => {
14
- toBe: (expected: T) => void;
15
- toEqual: (expected: unknown) => void;
16
- toBeNull: () => void;
17
- toBeTruthy: () => void;
18
- toContain: (expected: unknown) => void;
19
- };
20
- }
21
- export interface OrgStoreConformanceOptions {
22
- /** Name to show in test output (e.g. "local-provider"). */
23
- name: string;
24
- /** Factory that returns a fresh, empty store per test. */
25
- createStore: () => Promise<IOrgStore> | IOrgStore;
26
- /** Test runner globals. */
27
- runner: ConformanceRunner;
28
- /** If true, only test the default org (e.g. for single-org providers like LocalOrganizationProvider). */
29
- singleOrgMode?: boolean;
30
- }
31
- export declare function runOrgStoreConformance(opts: OrgStoreConformanceOptions): void;
32
- //# sourceMappingURL=orgStoreSuite.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"orgStoreSuite.d.ts","sourceRoot":"","sources":["../../src/testing/orgStoreSuite.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAItD,MAAM,WAAW,iBAAiB;IACjC,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,IAAI,KAAK,IAAI,CAAC;IACjD,EAAE,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,KAAK,IAAI,CAAC;IAC3D,MAAM,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,KAAK;QACzB,IAAI,EAAE,CAAC,QAAQ,EAAE,CAAC,KAAK,IAAI,CAAC;QAC5B,OAAO,EAAE,CAAC,QAAQ,EAAE,OAAO,KAAK,IAAI,CAAC;QACrC,QAAQ,EAAE,MAAM,IAAI,CAAC;QACrB,UAAU,EAAE,MAAM,IAAI,CAAC;QACvB,SAAS,EAAE,CAAC,QAAQ,EAAE,OAAO,KAAK,IAAI,CAAC;KACvC,CAAC;CACF;AAED,MAAM,WAAW,0BAA0B;IAC1C,2DAA2D;IAC3D,IAAI,EAAE,MAAM,CAAC;IACb,0DAA0D;IAC1D,WAAW,EAAE,MAAM,OAAO,CAAC,SAAS,CAAC,GAAG,SAAS,CAAC;IAClD,2BAA2B;IAC3B,MAAM,EAAE,iBAAiB,CAAC;IAC1B,yGAAyG;IACzG,aAAa,CAAC,EAAE,OAAO,CAAC;CACxB;AAsCD,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,0BAA0B,GAAG,IAAI,CA+V7E"}