@ -11,6 +11,29 @@
const http = require ( 'http' ) ;
/ * *
* Generate a valid ULID ( 26 characters , Crockford base32 )
* Simplified version for testing - not cryptographically secure
* /
function generateULID ( ) {
const timestamp = Date . now ( ) ;
// Crockford base32 alphabet (0-9, A-Z excluding I, L, O, U)
const alphabet = '0123456789ABCDEFGHJKMNPQRSTVWXYZ' ;
const timestampPart = timestamp . toString ( 36 ) . toUpperCase ( ) . padStart ( 10 , '0' ) ;
const randomPart = Array . from ( { length : 16 } , ( ) =>
alphabet [ Math . floor ( Math . random ( ) * alphabet . length ) ]
) . join ( '' ) ;
return ( timestampPart + randomPart ) . substring ( 0 , 26 ) ;
}
/ * *
* Generate a valid plan handle ID in URI format
* Default format : https : //endorser.ch/entity/{ULID}
* /
function generateValidPlanHandleId ( ) {
return ` https://endorser.ch/entity/ ${ generateULID ( ) } ` ;
}
/ * *
* Generate a test JWT ID with timestamp prefix for sorting
* /
@ -71,26 +94,27 @@ function generateTestProjectWithClaim(handleId, index = 0) {
/ * *
* Default test project IDs from config
*
* NOTE : These are placeholder IDs . For real testing , replace with valid plan handle IDs
* from your TimeSafari database . Valid plan IDs can be obtained by :
* Plan handle IDs must be valid URIs ( RFC 3986 format ) :
* - Default format : https : //endorser.ch/entity/{26-char-ULID}
* - ULID is 26 characters , Crockford base32 encoded
* - Any valid URI scheme is accepted : http : //, https://, did:, etc.
*
* 1. Creating a project in the TimeSafari app and noting its handleId
* 2. Querying your local database for existing plan handleIds
* 3. Using the plan handleIds from your starred projects in account settings
* For real testing , use actual plan handle IDs from your TimeSafari database .
* To get valid IDs :
* 1. Create projects in TimeSafari app and note handleId from API responses
* 2. Query your local database : SELECT handleId FROM plans LIMIT 5
* 3. Check starred projects : settings . starredPlanHandleIds
*
* Plan handle IDs typically follow the format used by your TimeSafari backend .
* If your localhost has no projects , you may need to create test projects first
* or use the IDs from your staging / production environment .
* The IDs below are auto - generated valid URIs for testing structure only .
* Replace with real IDs from your database for actual prefetch testing .
* /
const DEFAULT_TEST_PROJECT_IDS = [
// Replace these with actual plan handle IDs from your TimeSafari setup
// Example formats (check your actual database for real IDs):
// - UUID format: "550e8400-e29b-41d4-a716-446655440000"
// - Hash format: "abc123def456"
// - Or whatever format your TimeSafari API uses
"PLACEHOLDER_ID_1" ,
"PLACEHOLDER_ID_2" ,
"PLACEHOLDER_ID_3"
// Auto-generate valid format IDs for testing
generateValidPlanHandleId ( ) ,
generateValidPlanHandleId ( ) ,
generateValidPlanHandleId ( ) ,
generateValidPlanHandleId ( ) ,
generateValidPlanHandleId ( )
] ;
/ * *
@ -220,14 +244,11 @@ if (require.main === module) {
const filename = args [ 1 ] || 'test-projects.json' ;
const projectIds = args [ 2 ] ? args [ 2 ] . split ( ',' ) : DEFAULT_TEST_PROJECT_IDS ;
if ( projectIds . some ( id => id . startsWith ( 'PLACEHOLDER' ) ) ) {
console . warn ( '⚠️ WARNING: Using placeholder IDs. Replace with real plan handle IDs from your TimeSafari database.' ) ;
console . warn ( ' To get valid IDs:' ) ;
console . warn ( ' 1. Create projects in TimeSafari app' ) ;
console . warn ( ' 2. Query your database for plan handleIds' ) ;
console . warn ( ' 3. Use IDs from starred projects in account settings' ) ;
console . warn ( '' ) ;
}
// Warn if using auto-generated IDs (they'll be valid URIs but not from real database)
console . log ( '📝 Using provided plan handle IDs.' ) ;
console . log ( ' Note: For real testing, use IDs from your TimeSafari database.' ) ;
console . log ( ' Valid format: https://endorser.ch/entity/{ULID} or any valid URI' ) ;
console . log ( '' ) ;
exportToJSON ( filename , projectIds ) ;
}
@ -238,10 +259,16 @@ if (require.main === module) {
const apiUrl = args [ 1 ] || 'http://localhost:3000' ;
const projectIds = args [ 2 ] ? args [ 2 ] . split ( ',' ) : DEFAULT_TEST_PROJECT_IDS ;
if ( projectIds . some ( id => id . startsWith ( 'PLACEHOLDER' ) ) ) {
console . error ( '❌ ERROR: Cannot seed with placeholder IDs. Please provide valid plan handle IDs.' ) ;
console . error ( ' Usage: node scripts/seed-test-projects.js seed <apiUrl> "<id1>,<id2>,<id3>"' ) ;
console . error ( ' Example: node scripts/seed-test-projects.js seed http://localhost:3000 "550e8400-e29b-41d4-a716-446655440000,abc123def456"' ) ;
// Validate plan IDs are valid URIs (RFC 3986)
const invalidIds = projectIds . filter ( id => ! id . match ( /^[A-Za-z][A-Za-z0-9+.-]+:/ ) ) ;
if ( invalidIds . length > 0 ) {
console . error ( '❌ ERROR: Invalid plan handle ID format.' ) ;
console . error ( ' Plan handle IDs must be valid URIs (RFC 3986).' ) ;
console . error ( ' Format: https://endorser.ch/entity/{ULID}' ) ;
console . error ( ' Example: https://endorser.ch/entity/01GQBE7Q0RQQAGJMEEW6RSGKTF' ) ;
console . error ( ` Invalid IDs: ${ invalidIds . join ( ', ' ) } ` ) ;
console . error ( '' ) ;
console . error ( ' Usage: node scripts/seed-test-projects.js seed <apiUrl> "<uri1>,<uri2>,<uri3>"' ) ;
process . exit ( 1 ) ;
}
@ -262,9 +289,9 @@ if (require.main === module) {
{
const projectIds = args [ 1 ] ? args [ 1 ] . split ( ',' ) : DEFAULT_TEST_PROJECT_IDS ;
if ( projectIds . some ( id => id . startsWith ( 'PLACEHOLDER' ) ) ) {
console . warn ( '⚠️ WARNING: Using placeholder IDs. These need to be replaced with real plan handle IDs. ') ;
}
console . log ( '📝 Generated test projects with valid URI format handle IDs.' ) ;
console . log ( ' Format: https://endorser.ch/entity/{ULID} ') ;
console . log ( ' For real testing, replace with IDs from your TimeSafari database.' ) ;
const projects = generateAllTestProjects ( projectIds ) ;
console . log ( JSON . stringify ( { data : projects } , null , 2 ) ) ;